return_false
return_false

Reputation: 31

How to show which branches got merged into master today

I know that I can do

git branch --merged

to show what got merged but it just outputs everything. Is there a way to filter by date?

Upvotes: 0

Views: 101

Answers (1)

torek
torek

Reputation: 487725

No and yes, depending on what you really intend to ask.

Branch labels are temporary things, created and destroyed at whim. Here's a commit graph in which a branch was created, two commits were added on one side (the new branch), one commit added on another side (the original branch), the two sides were merged, and another commit was added at the end. Somewhere along the way, the name of the branch merged-in was deleted.

I have marked the actual merge commit with an asterisk *; the remaining commit nodes are just ordinary o nodes.

Note that there are no extra branch labels here, just the main-line.

o--o--o---*--o   <-- mainline
    \    /
     o--o

If you ask which branches are merged into mainline, only mainline itself is.

Now let's add another branch label, to make it clearer how the situation arose:

$ git branch aux mainline~1^2

The graph is now exactly the same, but we've added a branch label called aux:

o--o--o---*--o   <-- mainline
    \    /
     o--o        <-- aux

If you ask which branches are merged into mainline, the answer is now mainline itself and also aux.

When was aux merged into mainline? It wasn't: the branch was named zorg when it was merged. That name got deleted and a new name was created so that aux would come out of git branch --merged.

Let's add a third branch label, just to illustrate that it can be even worse:

$ git branch newbranch mainline~3

giving:

     ............<-- newbranch
    .
o--o--o---*--o   <-- mainline
    \    /
     o--o        <-- aux

What you can find out (it's not quite trivial, it requires a little fancy footwork) is when the merge commit(s) of interest were created. In this case, that's the * commit. It's a descendent of the commit now labeled aux (and previously zorg), and in this particular case it's an immediate parent (the second parent) of that commit.

Note that this will ignore branches that are not specifically merged into your branch, such as newbranch. In this case newbranch is a branch that can grow (but has not yet grown) from a commit earlier than the tip of mainline. (git branch --merged will list it, and you might, or might not, want to count it.)

Of course, the name zorg is long gone (branch labels being naturally temporary in git) and if someone sneaks in and deletes the name aux that we just created, so is that one. Or, if someone adds a new commit on the now-named aux branch, we get this new graph:

o--o--o---*--o   <-- mainline
    \    /
     o--o--o     <-- aux

and now the * commit is no longer a direct descendent of the commit labeled aux. However, we can determine that * is a direct descendent of an ancestor of the commit labeled aux. But we cannot (without extra help) reconstruct the fact that aux~1 used to be named zorg, and zorg was merged into mainline, while aux is no longer merged into mainline.

So, the question you need to answer for yourself is how much stock to put into these branch label names, that can be created and removed at will; and whether looking for merge commits and comparing them to the commit to which the branch-name points "counts"; and then ask if one of the two dates on the commit suffices as your filter.

There are two dates, "author" and "committer", along with two user names and email addresses. You probably want the committer date, although often the two are the same, and for merges, it's particularly rare to have different ones. Also, note that you may need to allow for time zones (depending on how you do your own "is it today" test).


How to get the commit date

For each branch b that git branch --merged claims is merged into your target branch (let's call the target t)...

  1. We know that the commit to which the name b points is an ancestor of the commit to which t points. Use git rev-parse to get the raw SHA-1s for each b.
  2. Using git rev-list --merges t, we can find revisions that are merge commits that are ancestors of t.
  3. For each SHA-1 extracted, look at all its parent commit IDs (you can have git rev-list produce these along with the commit; see --parents).
  4. If a parent matches the ID of one of any of the branches b, you have the merge-commit that merged branch b into t. So check the dates on that merge commit. In any case, remove the SHA-1 for b from your list of items needed for date-checking.

Repeat the above until all SHA-1s for all branches b are consumed, or you run out of merges.

Upvotes: 2

Related Questions