bojee
bojee

Reputation: 1

How to compare different patches of same commit with "git diff"?

Imagine a scenario when running this line of code on a feature branch in git:

git diff --quiet master feature -- file_path/* || echo Changed

The first statement will exit with 0 if there is a change to any file in the specified file path. And then the next command to the right will echo "Changed" to indicate that there are changes relative to the master branch.

I wish to do something similar but in the scenario when comparing a commit with itself relative to previous amends.

So if I have commit A (patch 1) and make some change and run "git commit --amend" the commit is amended and let's call this B (patch 2). A will be the first patch and B will be the second (as it will typically be in Gerrit).

Is it possible to check "diff" between the two patches to see which files have been changed since last "git commit --amend" command?

So ideally i would like to compare patch X relative to patch Y of a commit with something like "git diff" that specifies changed or updated files.

Upvotes: 0

Views: 588

Answers (1)

knittl
knittl

Reputation: 265845

It is critical to understand that commits in Git are immutable. Once created, they can never be changed again. git commit --amend does not change nor remove existing commits; instead, it moves HEAD (your current branch) back by one commit, then recreates the previous HEAD commit with the same tree and same commit message. The old commit is not lost (yet), it only became unreachable from your current ref. If you have another branch or tag point to it or any of its child commits, it would still be reachable through that other ref.

Git keeps track of all commits to which HEAD and other refs pointed, by means of the reflog. git reflog will show you the reflog entries.

Since you specifically mentioned Gerrit: Gerrit keeps refs for each patch in a patch set. Those refs are stored in the refs/changes namespace.

Gerrit uses the refs/for/ prefix to map the concept of "Pushing for Review" to the git protocol. For the git client, it looks like every push goes to the same branch, such as refs/for/master. In fact, for each commit pushed to this ref, Gerrit creates a new ref under a refs/changes/ namespace, which Gerrit uses to track these commits. These references use the following format:

refs/changes/[CD]/[ABCD]/[EF]

Where:

  • [CD] is the last two digits of the change number
  • [ABCD] is the change number
  • [EF] is the patch set number

For example:

refs/changes/20/884120/1

https://gerrit-documentation.storage.googleapis.com/Documentation/3.6.2/concept-refs-for-namespace.html

You can fetch these refs and then use them to diff the different commits directly:

git config --add remote.origin.fetch '+refs/changes/*:refs/gerrit/changes/*'

This will then fetch all the Gerrit refs into a local gerrit/ branch namespace, e.g. gerrit/changes/20/884120/1.

Subsequently, getting the difference between two versions of a patch set becomes as simple as:

git fetch
git diff gerrit/changes/20/88420/1 gerrit/changes/20/88420/2

Upvotes: 1

Related Questions