git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Timo Funke <timoses@msn.com>
Cc: "git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: Weird behaviour of git diff-index in container
Date: Mon, 9 May 2022 19:42:42 -0700	[thread overview]
Message-ID: <YnnRIq3kudurSq4c@google.com> (raw)
In-Reply-To: <VI1PR0402MB28779C7A41783472B2EF6823BFC69@VI1PR0402MB2877.eurprd04.prod.outlook.com>

Hi!

Timo Funke wrote:

> podman run --rm -it -v `pwd`:/git:z --entrypoint sh docker.io/alpine
> > container# apk add git
> > container# cd /git
> > container# git diff-index --quiet HEAD -- ; echo $?
> 1
> > container# git diff-index --quiet HEAD -- ; echo $?
> 1
> > container# git status
> On branch master
> nothing to commit, working tree clean
> > container# git diff-index --quiet HEAD -- ; echo $?
> 0
>
>
> What did you expect to happen? (Expected behavior)
> `git diff-index --quiet HEAD -- ; echo $?` should return `0`
> even without executing `git status`.
>
> What happened instead? (Actual behavior)
> Without executing `git status` `git diff-index --quiet HEAD -- ; echo $?`
> will repeatedly print `1`.
>
> What's different between what you expected and what actually happened?
> It is odd that `git diff-index --quiet HEAD -- ; echo $?` prints
> different results depending on whether `git status` was executed.

I love this example.  Thanks for writing.

I checked "git help diff-index" to see whether it describes this
pitfall, and I didn't see an explanation.  So at the very least you
have uncovered a documentation bug.

The difference between diff-index and status here is a difference
between "porcelain" (user-facing) commands and "plumbing"
(script-facing) commands.  In Git's index file there is stat(2)
information for each file; if that stat(2) information matches the
corresponding file in the working directory then we know it hasn't
been modified relative to what is in the index.  If the stat(2)
information differs from the working copy, on the other hand, the
behavior depends on whether the command being run is porcelain or
plumbing:

 - plumbing commands assume that the script author has run "git
   update-index --refresh -q" first to update the stat(2) information
   if the file hasn't changed.  This allows efficient scripts to
   refresh the index once and then run multiple commands that rely on
   the result of that:

	git update-index --refresh -q || :
	for rev in "${revs[@]}"
	do
		if git diff-index --quiet "$rev" --
		then
			... do something ...
		fi
	done

 - porcelain commands such as "git status" implicitly refresh the
   index before doing anything else.  This allows them to produce the
   expected result even if the repository is a copy made using "cp -a"
   or has been transferred across machines on a USB stick.

Some places I expected to find an explanation of this:

- documentation for the "git diff-index" command ("git help
  diff-index").  It does not mention this behavior.

- documentation for the "git diff" command ("git help diff").  It also
  doesn't mention this.  That's particularly surprising because it
  would be a great place to document the diff.autoRefreshIndex setting
  that affects this behavior of the "git diff" command (described in
  Documentation/config/diff.txt).

- the Git user manual (Documentation/user-manual.txt).  It describes
  "git update-index --refresh" but very briefly.  It doesn't describe
  the above scripting pattern.

- Git's command-line conventions ("git help cli").  No mention.

- overview of plumbing and porcelain commands ("man git").  No
  mention.

- the Git scripting manual ("git help core-tutorial").  It describes
  "git update-index --refresh" after a "cp -a" but not its use in
  scripts.

- the history of Git's contrib/examples/.  This contains many examples
  of the above scripting pattern but is not very discoverable.

So there are many opportunities for someone to document this better.
If you'd be interested in pursuing that, I'd be happy to provide some
pointers.

Thanks,
Jonathan

  parent reply	other threads:[~2022-05-10  2:43 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-09 22:42 Weird behaviour of git diff-index in container Timo Funke
2022-05-09 23:18 ` Junio C Hamano
2022-05-10  2:42 ` Jonathan Nieder [this message]
2022-05-10 16:47   ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YnnRIq3kudurSq4c@google.com \
    --to=jrnieder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=timoses@msn.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).