hiquetj
hiquetj

Reputation: 420

How to get a list of commits and files of a pull request? (not through the UI)

I am trying to get log information similar to git log but with information specifically on a pull request. I would like to get the pull request's, that was just merged into master, files that were changed.

For instance, I have a pull request that was just merged. It changed File1, File2, and File4.

I also have another pull request that was just merged. It changed File1, File3.

I was hoping to be able to get the names of the files that are tied to a specific pull request.

My problem is that git log --oneline or git whatchanged -m or git log --pretty=format:"%H" --name-only does not show things in order, and it is hard to parse through because of the commits.

Is there anyway to retrieve the files edited from a pull request?

Upvotes: 4

Views: 6086

Answers (1)

torek
torek

Reputation: 489718

TL;DR

You probably want:

git diff-tree [options] <sha>^1 <sha>

as, e.g., produced by:

$ git diff-tree --abbrev bdae4af8705^1 bdae4af8705
:100644 100644 50c6b2ab1... 8cc34186c... M      setup.c
$ git diff-tree --name-status bdae4af8705^1 bdae4af8705
M       setup.c

Long

Well, first, it's important to distinguish between a pull request, which is not something Git defines,1 and a merge commit, which is. As far as Git is concerned, a pull request is just any other commit. Until you merge it, you'd have to find or specify a second commit somehow. What you're looking at is the after-effect of having already clicked some clicky-button marked "merge pull request", on some web page.

I say all this not to be pedantic,2 but because this is a good thing, as it means you now have a merge commit that you have obtained by running git fetch. (If you have not already used git fetch to obtain the merge commit, do that first.) This simplifies the problem! Instead of having to search all the commits that were merged, you can look only at the merge commit itself:

... git whatchanged -m ... does not show things in order ...

Using git log -mgit whatchanged is really just git log --raw so you are doing that—is sort of the way to go. It's not clear to me what you mean by "does not show things in order": in fact, it shows things in a very precise and controlled order, as we can see by running, e.g.:

git log --raw -m bdae4af87053490adad2dc9fb184d6d050d46a4c

on a Git repository for Git:

$ git log --raw -m bdae4af87053490adad2dc9fb184d6d050d46a4c
commit bdae4af87053490adad2dc9fb184d6d050d46a4c (from 8d7fefaac4318ac3155368f475e10f97714ebd47)
Merge: 8d7fefaac 176b2d328
Author: Junio C Hamano <[email protected]>
Date:   Tue Dec 19 11:33:58 2017 -0800

    Merge branch 'sg/setup-doc-update'

    Comment update.

    * sg/setup-doc-update:
      setup.c: fix comment about order of .git directory discovery

:100644 100644 50c6b2ab1... 8cc34186c... M      setup.c

commit bdae4af87053490adad2dc9fb184d6d050d46a4c (from 176b2d328ccc305aa2e565c39ad7b0fb24099275)
Merge: 8d7fefaac 176b2d328
Author: Junio C Hamano <[email protected]>
Date:   Tue Dec 19 11:33:58 2017 -0800

    Merge branch 'sg/setup-doc-update'

    Comment update.

    * sg/setup-doc-update:
      setup.c: fix comment about order of .git directory discovery

:000000 100644 000000000... 611ab4750... A      .clang-format
:100644 100644 320e33c32... 8ce9c6b88... M      .gitattributes
:000000 100644 000000000... 64e605a02... A      .github/CONTRIBUTING.md
[mass snippage]

This is the output anyone will always get for this particular commit: it first compares the commit itself, hash ID bdae4af87053490adad2dc9fb184d6d050d46a4c, against its first parent 8d7fefaac4318ac3155368f475e10f97714ebd47. There is only one file changed in this comparison, namely setup.c, which is modified.

It then compares commit bdae4af87053490adad2dc9fb184d6d050d46a4c against its second parent 176b2d328ccc305aa2e565c39ad7b0fb24099275. This time, there are many files changed and added.

The first parent is the commit that was the tip of the branch before the git merge. The second commit is the commit that was the argument to git merge (this being a normal merge with two parents; if this were an octopus merge, the output would go on to show the new commit against the third parent, and so on).

When Git performs a merge, it does so by:

  • locating the merge base commit (or in some rare cases, when there is more than one merge base, constructing a new commit that serves as the merge base);
  • comparing the merge base commit to the current (HEAD) commit, obtaining the --ours change-set;
  • comparing the merge base commit to the other commit (assuming a standard two-commit merge), obtaining the --theirs change-set; and
  • combining the changes found in these two change-sets to the base.

If Git successfully combines these on its own, Git goes on to make the new merge commit on its own as well. If not, it stops and gets help from the user. In any case the result is a new commit, with a new hash ID, whose parents are the --ours commit (the old HEAD commit) and the --theirs commit, specifically in that order.

This means that the first git log output section shows precisely those changes obtained from the --theirs branch (vs the merge base) that were not already present in the --ours branch. The second git log output section, showing the merge commit vs its second parent, shows the changes obtained from the --ours branch (vs the merge base) that were not already present in the --theirs branch.

In general, the first such section is the interesting one.

You can obtain just the diffs (and shrink them with --name-status, for instance) using git diff or (for git whatchanged / git log --raw style output) git diff-tree and specifying, in whichever order you like, the merge commit hash and the first-parent commit hash, or anything that resolves to the first-parent commit hash.


1Git has a git request-pull command, but that's not what you are using when you click a clicky-button on a web server.

2OK, not just to be pedantic. :-)

Upvotes: 6

Related Questions