9

I have a feature branch concisely named feature that has about 100 commits all related to a feature of sorts. These commits were all merged into the master branch over the time. I want to list all commits that were on the branch so I can re-add the feature to other project.

Basically I want to have commit IDs for the green dots on the graph below.

relevant commits

How can I do that in Git other then by going to gitk or similar tool and hand-collecting all the relevant commit IDs?

sanmai
  • 29,083
  • 12
  • 64
  • 76

3 Answers3

6

If you get the starting point of the specific branch, e.g., SHA1, try this:

git log --pretty=oneline SHA1^..feature
yuwang
  • 846
  • 11
  • 24
3

Despite answer is given and accepted I would suggest more automatic way for doing this (but it will only work if you did not merge your master to feature):

Considering the following history:

--A---B---C---D---E---F---G (master)
       \     /       /
        H---J-------K       (feature)

Basically we want to perform git log B..feature.

git log --format='%H' feature..master | tail -1 | \
xargs -I '{}' git log '{}'^..feature

git log --format='%H' feature..master | tail -1 will find the commit to the master that was done right after you created feature branch - this is C

And ancestor of C - B will also be the ancestor of the first commit H of feature branch.

Then xargs -I '{}' git log '{}'^..feature (that is turns to git log B..feature) just shows the commits that is reachable from feature but don't reachable from the B.

Max Komarychev
  • 2,836
  • 1
  • 21
  • 32
  • 2
    I have a somewhat messy beginning of the `feature` branch requiring to hand-pick starting commit, but otherwise your recipe works just fine. Here's one-liner: `git log $(git rev-list feature..master | tail -1)^..feature` – sanmai Jul 22 '13 at 08:06
  • 2
    see [Finding a branch point with Git?](http://stackoverflow.com/q/1527234) for details on how to find a branch start point – CharlesB Jul 22 '13 at 10:23
0

A simpler version, possible with Git 2.36 (Q2 2022):

git log --exclude-first-parent-only feature ^master

That will list all commits from feature branch.


With Git 2.36 (Q2 2022), "git log"(man) and friends learned an option --exclude-first-parent-only to propagate UNINTERESTING bit down only along the first-parent chain, just like --first-parent option shows commits that lack the UNINTERESTING bit only along the first-parent chain.

See commit 9d505b7 (11 Jan 2022) by Jerry Zhang (jerry-skydio).
(Merged by Junio C Hamano -- gitster -- in commit 708cbef, 17 Feb 2022)

git-rev-list: add --exclude-first-parent-only flag

Signed-off-by: Jerry Zhang

It is useful to know when a branch first diverged in history from some integration branch in order to be able to enumerate the user's local changes.
However, these local changes can include arbitrary merges, so it is necessary to ignore this merge structure when finding the divergence point.

In order to do this, teach the "rev-list" family to accept "--exclude-first-parent-only", which restricts the traversal of excluded commits to only follow first parent links.

-A-----E-F-G--main
  \   / /
   B-C-D--topic

In this example, the goal is to return the set {B, C, D} which represents a topic branch that has been merged into main branch.
git rev-list topic ^main(man) will end up returning no commits since excluding main will end up traversing the commits on topic as well.
git rev-list --exclude-first-parent-only topic ^main(man) however will return {B, C, D} as desired.

Add docs for the new flag, and clarify the doc for --first-parent to indicate that it applies to traversing the set of included commits only.

rev-list-options now includes in its man page:

When finding commits to include, follow only the first parent commit upon seeing a merge commit.

This option can give a better overview when viewing the evolution of a particular topic branch, because merges into a topic branch tend to be only about adjusting to updated upstream from time to time, and this option allows you to ignore the individual commits brought in to your history by such a merge.

rev-list-options now includes in its man page:

--exclude-first-parent-only

When finding commits to exclude (with a '{caret}'), follow only the first parent commit upon seeing a merge commit.

This can be used to find the set of changes in a topic branch from the point where it diverged from the remote branch, given that arbitrary merges can be valid topic branch changes.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250