0

I have a python script that runs on Jenkins that lists files in the current commit to the master. I am using the command below in my script to help list the files

git diff-tree --no-commit-id --name-only -r HEAD

However i am running into an issue because this command only works if the commit has contains files that were directly pushed to master. I guess my question is, does anyone happen to know a command that will also list files if they were initially pushed to another branch and later merged into master?

LeGEC
  • 29,595
  • 2
  • 37
  • 78
  • Hi, and welcome. I'm not sure I understand. Listing the files in the master commit is `git ls-files master`. Could you provide a bit more detail, perhaps an example, and what the list of files would be used for? – Schwern Mar 01 '21 at 02:41
  • @Schwern, I have script that validates that certain key value pairs in some json files are not the same. So I use "git diff-tree --no-commit-id --name-only -r HEAD" to check the current commit hash and find the changed files and then run the rest of my code to do the validation. This only works when i run it after I push the code straight to master. But whenever i create another branch, push the code to that branch and merge the new branch into master, the jenkins build runs that git commands agains the new commit hash from the merge and finds no files in there. – user9108802 Mar 01 '21 at 03:17
  • I'm still not sure what the purpose of this is, but the approach of trying to determine what branch a change was made in seems fragile. Are you checking the pairs are not the same between different files in the same commit, like A.json and B.json? Or are you checking if A.json changed some pairs between commits? Is this running on any commit on any branch? Or just commits to master? – Schwern Mar 01 '21 at 16:10

2 Answers2

0

You're trying to use git diff-tree to see show the files that comprise a commit, but a merge commit has no files; it exists only to mark the merge of one branch into another one. You need to point diff-tree at a commit that actually contains changes.

You can probably get what you want by looking at the first non-merge commit in your history. For example:

git diff-tree --no-commit-id --name-only -r $(git rev-list --no-merges -1 HEAD)

The git rev-list command outputs the id of the first non-merge commit on the current branch, which is then passed to the git diff-tree command.

larsks
  • 194,279
  • 34
  • 297
  • 301
0

If you know that you are working from on a merge commit, you can list the files modified by the "merged branch" using :

git diff --name-only HEAD^...HEAD^2   # three dots

You may replace --name-only with --name-status if you want to also have an annotation saying if a file was added, modified or deleted.

If you need to know if a commit is a merge commit or a "regular" commit, you can check the answers to this question.
For example, adapting @MarekR's answer :

head_is_merge () {
    # the return code of `git rev-parse HEAD^2` will say if it is a merge commit
    git rev-parse HEAD^2 > /dev/null 2> /dev/null
}

if head_is_merge; then
    # HEAD is a merge commit
else
    # HEAD is a regular commit
fi

Some explanations :

  • HEAD^ (resp. HEAD^2) points to the first parent (resp. the second parent) of the active commit.
    obviously : HEAD^2 exists only if the active commit is a merge commit ; if it isn't, git will error
  • git diff A...B is a shortcut, to indicate "the diff from the point where A and B forked, and B itself"

from git help diff :

git diff [<options>] <commit>...<commit> [--] [<path>…​]

This form is to view the changes on the branch containing and up to the second <commit>, starting at a common ancestor of both <commit>. git diff A...B is equivalent to git diff $(git merge-base A B) B.

LeGEC
  • 29,595
  • 2
  • 37
  • 78