Git - 如何找到特定分支的第一个提交

150

在下面的树形示例中:

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

我正在寻找 xxx 分支中的第一次提交 F。我认为可以通过以下方式实现:

git log xxx --not master

最后列出的提交应该是F。这是正确的解决方案吗,还是存在一些缺点?

我知道在stackoverflow上有类似的问题,但没有人提出这样的解决方案,我也不确定我是否做对了。


可能是 https://dev59.com/XW025IYBdhLWcg3wW0oc 的重复问题。 - nyzm
8个回答

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

"branch"是你特定的分支名称。点点给出了该分支具有而主分支没有的所有提交记录。tail -1从先前输出结果中返回最后一行。


4
如果branch已删除,那么这只有在分支存在的情况下才有效。你应该如何操作? - oz123
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Zitrax
7
没有给我我期望的东西。我的分支(旧的)已经合并回主分支了,这意味着 xxx 中的所有提交已经包含在主分支中了。尽管如此,我仍然需要知道哪个提交是该分支上的第一个提交,或者说,我需要检查该分支独有的提交历史记录,不关心它们是否在主分支上。 - Motti Shneor
2
@MottiShneor 根据你的合并方式,这可能会有些棘手。如果你使用了快进合并,就好像该分支从未存在过一样。否则,你可能会对这个答案感兴趣,它列出了许多找到分支点的方法。一旦你有了分支点,SHA可以替换master,只要你的分支没有被删除,git log <sha>..branch --oneline | tail -1仍然可以给你想要的结果。 - ND Geek
1
你可以使用 --reverse 参数来倒序阅读日志,并带有颜色等特性。 - Dominik

26
git cherry master -v | head -n 1

cherry - 显示你当前分支上未被上游分支包含的提交记录(文档)。在此情况下,上游分支(即主分支)是你当前分支派生出来的一个点。

-v - 显示提交名称(而不仅仅是SHA)- 详细模式。

head - Unix 命令,打印文本中的前 n 行。


1
在相关分支内运行此命令。 - Russo

14

你应该使用merge-base功能,它专门设计用于解决这个问题:

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

2
如果您想返回原始分支点,我认为这种方法行不通。如果您将develop合并到<branch>中,则合并基准将比原始分支点更新。 - Alexander Mills
9
这并不指向 F,而是指向主分支中的一个提交(虽然在 OP 的图示中很难看出来,似乎是 B 或 C)。 - Romain Valeri

2

如果您的旧分支再次合并回主分支时没有得到预期的结果。我使用python脚本查找初始分支提交ID。

git rev-list --first-parent changeset

--first-parent仅在看到合并提交时跟随第一个父提交。

从上述命令迭代changeset,直到找到父分支。

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)

1
git cherry master -v | tail -1   

然而,这只会给你分支xxx中第一个不在主分支上的提交记录,而不是xxx分支上的第一个提交记录。如果xxx分支已被删除和/或重新创建了一次或多次,则后者将很困难。在这种情况下,你可以尝试以下方法:
git reflog | grep checkout | grep xxx | tail -1   

4
你的意思是想要写 head -n 1 而不是 tail -1 吗?tail -1 返回的是最新的提交而不是第一个。 - Nelu
以上第一条建议对我不起作用。在将“master”更改为我的当前存储库上的默认分支“main”之后(“master”会从git中产生致命错误),它会给出最近的提交而不是最旧的提交。第二个建议可以正常工作。 - arielf

0

非常简单:您可以使用此方法直接获取功能分支中第一次提交的哈希值:

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

0

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

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


在我的代码库中,这显示的是自上次将主分支合并到xxx分支以来的第一次提交,而不是xxx分支的第一次提交。 - jk7
对我来说,这是所有列在这里的答案中最好的。我认为它以最佳方式回答了问题(假设该分支尚未合并回主分支)。 - Eyal Gerber

-2

我尝试了这个命令,它有效:

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

2
请不要添加与同一帖子上已有答案材料相关的跟帖回复:https://dev59.com/32Ml5IYBdhLWcg3wbGh1#32870852。 - hakre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接