166

In following example tree:

A-B-C-D-E (master branch)
    \
     F-G-H (xxx branch)

I'm looking for F - the first commit in xxx branch. I think that it is possible with:

git log xxx --not master

and the last listed commit should be F. Is it correct solution or maybe there are some disadvantages of it?

I know that there were similar questions on stackoverflow, but nobody proposed such solution, and I'm not sure if I do it right.

1

8 Answers 8

190
git log master..branch --oneline | tail -1

Where "branch" is your specific branch name. The dot-dot gives you all of the commits that the branch has that master doesn't have. tail -1 returns the last line from the previous output.

Sign up to request clarification or add additional context in comments.

5 Comments

this only works if `branch``exists. How would you do it if branch is deleted?
@Oz123 branch can be replaced by any ref, like HEAD or a sha1 or a tag. But obviously you need some kind of reference.
Doesn't give me what I was expecting. My branch (old one) was already merged back to master, which means all commits in xxx are already in master. Still - I need to know which commit WAS the first one on that branch - or actually - I need to examine the history of commits of that branch alone - I don't care if they're on master or not.
@MottiShneor depending on how you merged, that could be tricky. If you did a fast-forward, it's as if the branch never existed. Otherwise, you may be interested in this answer, which lists a number of ways to find the branch point. Once you have your branch point, the SHA can replace master, and as long as your branch hasn't been deleted, git log <sha>..branch --oneline | tail -1 should still give you the results you're looking for.
You can use --reverse to read the logs backwards with colors, etc.
32
git cherry master -v | head -n 1

cherry - Shows the commits on your current branch which aren't present on a branch upstream (docs). Upstream (master in this case) is where you consider your current branch to have derived from.

-v - Shows commit names (instead of just SHA's) - verbose.

head - Unix command which prints n number of lines from a text

1 Comment

run this command inside the branch in question
16

You should use the merge-base functionality which is designed to solve exactly this:

git merge-base remotes/origin/<branch> develop 

2 Comments

I don't think this will work if you desire to go back to the original fork point. If you merge develop into <branch> the merge-base will be newer than the original fork point.
Also, this would not point to F, but to a commit in master branch (although difficult to see in OP's drawing, seems to be B or C).
2
git cherry master -v | tail -1   

however this will only give you the first commit on branch xxx that is not in master, not the first commit on branch xxx ever. the latter would be difficult if branch xxx has been deleted and/or re-created one or more times. it that case you could try the following:

git reflog | grep checkout | grep xxx | tail -1   

2 Comments

Did you mean to write head -n 1 instead of tail -1? tail -1 returns the most recent commit instead of the first.
The first suggestion above doesn't work for me. After changing master to main which is the default branch on my current repo (master gives a fatal error from git). It gives the most recent commit instead of the oldest. The 2nd suggestion works fine.
2

If your branch (old one) once again merged back to master doesn't give expected result. I have using python script to find initial branch commit Id.

git rev-list --first-parent changeset

--first-parent follow only the first parent commit upon seeing a merge commit.

Iterate changeset's from above command until parent branch found.

def status_check(exec_command, exec_dir=None, background=False):
    if exec_dir:
        os.chdir(exec_dir)
    res = subprocess.Popen(exec_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if not background:
        result = res.communicate()
    return result



def findNewBranchCommits(changeset=None):
    cmd = "git rev-list --first-parent "+ changeset
    rev_list = status_check(cmd,self.module_dir)
    rev_list = str(rev_list[0]).split('\n')
    rev_list = list(filter(None, rev_list))
    for x in rev_list:                      # Iterate until branch base point
        rev_cmd = "git branch --contains " + x
        rev_cmd = status_check(rev_cmd,self.module_dir)
        rev_cmd = str(rev_cmd[0]).split('\n')
        if(len(rev_cmd) > 2): 
            print "First Commit in xxx branch",x
            break

findNewBranchCommits(changeset)

Comments

0

git rev-list --ancestry-path $(git merge-base master xxx)..xxx | tail -1

2 Comments

In my repo this shows the 1st commit since the last merge from master into branch xxx, not the 1st commit of branch xxx.
For me this worked the best of all the answers listed here. I think it answers the question the best way (assuming the branch isn't merged back to master)
0

Its very simple: You can use this to directly get the hash of the first commit in the feature branch:

git log <source_branch>..<feature_branch> --pretty=format:%h

1 Comment

This shows every commit hash, not the first commit as requested.
-3

I tried this command and it worked:

git log <source_branch> <feature_branch> --oneline | tail -1

1 Comment

Please do not add me-too answers that relate to already existing answer material on the same post: stackoverflow.com/a/32870852/367456

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.