如何找到一个分支的第一次提交?

15
假设以下图表:

Assume the following graph:

A -- B -- C -- D -- E -- F
      \
       G -- H -- I

我希望找到G,以便能够进行交互式变基以压缩提交(但仍保留主题分支上的一个提交),该提交将在稍后进行审核和合并。我不想只是变基整个分支,因为我想保留分支存在且已合并的信息。

(我知道可以查看历史记录并使用提交的SHA校验和,但我正在寻找一种方法,可以在不手动查找信息或计算有多少提交并使用来自HEAD的~号的情况下完成它)。

编辑:我想要实现的目标的澄清:

我想要避免这种情况:

A -- B -- C -- D -- E -- F -- J
      \                      /
       G -- H -- I -- -- -- -

而是要有类似这样的东西:

A -- B -- C -- D -- E -- F -- J
      \                      /
       G' -- -- -- -- -- -- -

换句话说,我想在主题分支上使用交互式变基将提交压缩为一个,但仍保留该分支并使用常规合并将更改从主题分支集成到主分支。


请参考以下链接:https://dev59.com/LHI_5IYBdhLWcg3wF_F3 - Piet van Dongen
2
那是一个不同的问题。它甚至以我所说的方式进行解释。如果我们将其转化为我的例子,他正在寻找“B”,但我正在寻找“G”。 - Tamás Szelei
3个回答

23

在git中,“在一个分支上”的提交并不存在,只有从该分支可达的提交。而且这些信息并不能很好地指示该提交最初属于哪个分支。因此,我认为您的问题有两种解释:

  • 我想找到合并基础branchmaster后,在分支侧面的第一个提交。
  • 我想找到第一个从branch可达的提交,但从master不可达。

我假设你的意思是第二个。这个命令返回了答案:

 git rev-list ^master mybranch | tail -n 1

注意: 如果你在分支上创建与主题无关的分支,那么所有的操作都将失败。


我有点困惑你想要实现什么。如果你想让一个分支由一个提交来代表,但仍然能够进行合并,你应该这样做:

git checkout mybranch
git reset --soft `git merge-base mybranch master`
git commit -m 'All of Mybranch'
git checkout master
git merge --no-ff mybranch

请注意,这将从第一个合并基础开始进行压缩。如果您之前将 master 合并到 mybranch 中,则可能不是您想要的。您可以通过将第二个命令替换为以下内容来修改此设置以从mybranch的第一个提交开始,而不是从master开始(在复杂历史记录中可能会产生奇怪和意外的结果):

 git reset --soft `git rev-list ^master mybranch | tail -n 1`^

谢谢。我已经加了一个我想要做什么的解释,请看我的编辑。 - Tamás Szelei
我也是这么认为的 - 这正是我在我的回答中所解释的。 - Chronial
你能解释一下那两个符号之间的区别吗? - jberryman

7

使用git merge-base可以获得B

git merge-base F I

或者更简单地说,使用 <\p>
git merge-base my_branch my_other_branch

你可以使用rebase命令来将结果合并。
git rebase -i B

只需保留第一个提交 G,同时将其他提交压缩成一个。


1

git merge-base会给你B。你想要所有直接子节点B,同时也是I的祖先。这与如何在git中找到下一个提交?引用Git提交的子节点有关。尝试类似以下的命令:

root=$(git merge-base master topic-branch)

git rev-list --parents ^$root topic-branch | grep " $root" | cut -f1 -d' '

这将列出所有从根到 topic-branch 末尾的提交,包括它们的父级,并显示其中父级为 merge-base 根的提交。
因为一个主题分支可能包含合并,所以在一个分支中可能会有多个“第一”次提交,从拓扑结构上看。

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