1

I'm trying to get all the commit hashes that are coming in from a merge. My ultimate goal is to grab the emails of these commiters and email them if the merge breaks a build. However, I'm not sure how to approach this problem. This needs to be done entirely in the terminal because it will be automated by Jenkins.

One approach I've tried is possibly finding the commits between the merge commit and the last commit added to master. However, apparently these seem to be meshed by timestamps.

Another approach I've thought of is finding the branch that was merged into master, and just get all the hashes there. However, I don't know a command that does this.

I'm using this at the moment to find the merge commit hash (and email)

git log -1 --merges -pretty=format:%H
git log -1 --merges -pretty=format%ae

The expected result is that I should get the hashes of all the commits and being able to find the email addresses of these commiters.

Fua
  • 55
  • 9

2 Answers2

1

If you have the merge commit , try first:

git log --pretty=format:\"%%H\" M~...M

That would list all commits that are reachable from either M~ or M but not reachable from both M~ and M.

That would be all the commits done on the second parent of M.
Here below: M-x-x.

M
| \
M~ \
|   x
m   |
|   x
m   /
|  /
o  
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
1

I'm trying to get all the commit hashes that are coming in from a merge.

If you are controlling whether or not the merge gets performed, you have an ideal situation, because you can easily enumerate the commits that would be reachable after the merge that are not currently reachable before the merge begins. (Since the merge does not alter the earlier part of the graph, you can still get the same result after the merge.)

Let's say that you are on the commit whose hash is H at the tip of branch mainline, and you are about to—but have not yet—issued the command:

git merge feature

to bring in commits from feature that are not already from mainline, as in:

...--o--*--o--o--H   <-- mainline
         \
          E--F----G   <-- feature

The list of commits that this merge would bring in—which is not really as interesting as the changes that it will merge since it's possible that, for instance, F is simply a direct revert of E so that only commit G really matters—is simply those enumerated by:

git log mainline..feature

You may want to control the order of enumeration. See below, after the next quoted bit.

Note that after the merge, you have:

...--o--*--o--o--H--M   <-- mainline
         \         /
          E--F----G   <-- feature

and the commits that were brought in are those enumerated by M^1..M^2. (This assumes a simple two-tip merge that results in a true merge commit. Octopus merges are enumerable but need fancier syntax, and fast-forward merges do not record the previous tip of mainline and are problematic to analyze after-the-fact.)

One approach I've tried is possibly finding the commits between the merge commit and the last commit added to master. However, apparently these seem to be meshed by timestamps.

The git log command walks the commit graph using a priority queue. Your "meshed by timestamps" observation is due to the priority of items in the queue. You may simply want to control this priority, probably with --topo-order.

The overall loop is structured this way:

  • All inserts obey command line negations, e.g., --not foo excludes all commits reachable from the commit specified by foo including commit foo itself. (This affects both initialization, in the next point, and iteration, below.)

  • git log will initialize the queue by inserting as starting points all commits mentioned directly / positively on the command line. If no commits are mentioned, insert HEAD. ("Positively" here refers to the fact that B ^A has a positive reference to B and a negative reference to A. So A..B excludes the commits reachable from A, just like --not A does.)

  • Now, while the queue is non-empty, git log runs:

    • Remove the front commit off the queue and work with it.
    • Insert into the queue any parent(s) of that commit, as modified by any selected History Simplification or other options (including parent rewriting), that are not in the queue and have not yet been visited.

The overall process quits once the queue is empty.

Given that a merge has—by definition—two or more parent commits, any git log step that traverses a merge has the potential to insert two or more commits into the queue. Of course, the queue can also start with two or more commits in it. Whenever the queue does have two or more commits, it's the priority that determines which commit is in which position in the queue.

The default priority is by committer date, with higher values (later dates) moving to the front of the queue. However:

  • --date-order makes sure that children come ahead of parents. Otherwise it is the same as the default.

  • --author-date-order uses the author date instead of the committer date, and is otherwise the same as --date-order (parents come out after all of their descendants).

  • --topo-order avoids interleaving the legs of merges.

See the git log documentation for details. Note that --graph implies --topo-order.

torek
  • 448,244
  • 59
  • 642
  • 775