Skuli
Skuli

Reputation: 2067

Git: How to make sure that a group of files are identical to what they were at some time in the past

Lets say that someone makes a bad push and changes a file that he didn't mean to ( amazingly this happens sometimes ). Then say he realized it and reverted his mistake.

How can I verify that the file is unchanged afterwards, that is, how can i verify that he successfully undid his mistake?

How do you do the same for a group of files?

And finally, how do you do this if you are comparing files at a different time in history, where neither is the current version?

Upvotes: 1

Views: 107

Answers (3)

Bert F
Bert F

Reputation: 87533

https://www.kernel.org/pub/software/scm/git/docs/git-diff.html:

git diff [--options] <commit> <commit> [--] [<path>…]
This is to view the changes between two arbitrary <commit>.
...
<path>…
The <paths> parameters, when given, are used to limit the diff to the named
paths (you can give directory names and get diff for all files under them).

So:

git diff deadbeef cafebabe -- pom.xml src/main/resources src/test/resources

will let me see the differences between those two (abbreviated) commit hashes for my pom.xml and all the files under src/main/resources and src/test/resources.

[[ Keep in mind that this compares the full files/dirs as they exist at those revisions. It does not merely compare the specific changes introduced by those two specific commits. ]]

--

OP asks:

Can't you skip the -- ? That's what I did and didn't notice problems.

Absolutely. The -- option is to remove possible ambiguities in the command. In cases where the command is smart enough to resolve the ambiguity itself (as is usually the case with git commands), the '--' can be omitted (as indicated by the brackets around the -- in the man page).

What possible ambiguities? They are probably rare if you keep to sane filenames and branch/tag names, but they are possible. For example, note that the man page says there are both valid git diff commands:

(1) git diff [--options] [<commit>] [--] [<path>…]
This form is to view the changes you have in your working tree
relative to the named <commit>. ...

(2) git diff [--options] <commit> <commit> [--] [<path>…]
This is to view the changes between two arbitrary <commit>.

Let's say I have a file called 'foo' in the current directory. I also happen to have a tag called 'foo' (that's the commit where I added the file called 'foo').

git diff deadbeef foo

What does this command do? (1) Does it compare file foo from revision deadbeef to file foo as it is now in my work dir? (2) Or does it compare the whole source tree from revision deadbeef to the whole source tree in tag foo?

I believe it will do (2). So in case I really want interpretation (1), I can use:

git diff deadbeef -- foo

--

One thing nice about git is the commands are fairly consistent in structure. Many commands use:

git <command> [--options] <commit reference(s), if needed?> [--] [<path> ...]

git diff HEAD^ -- README 
git log HEAD^ -- README 
git checkout HEAD^ -- README 
git reset HEAD -- foo

Perhaps you won't run into ambiguities for git diff very often and if you did run into it, its any easy fix to run the command again using the '--'. But sometimes its nice to use the double-dash to ensure no ambiguity (or to resolve an ambiguity if there really is one), especially if the command is potentially destructive (e.g. checkout, reset).

Upvotes: 2

jthill
jthill

Reputation: 60295

If your requirement is exactly the title question, this will perform somewhat-to-noticeably better -- diff's extremely good, but comparing a pair of 20-byte codes you already have is always going to be better than extracting the of all differing files. rev-parse turns any reference into the sha of the object it refers to, so:

if test "$(git rev-parse commit1:path/to/file)" \
      = "$(git rev-parse commit2:path/to/maybe/another/file)"; then
        # the files are the same
else
        # they're different
fi

or if you're eyeballing it,

git rev-parse commit1:path/to/blob-or-tree commit2:path/to/another

will do the trick, though if directory trees differ you'll sooner or later use git diff --name-only on the two tree refs to find which ones.

Upvotes: 0

Katriel
Katriel

Reputation: 123632

Diff the file with itself:

git diff HEAD^^ HEAD file

If you leave off the file it'll diff the commits.

Upvotes: 1

Related Questions