如何查看一个分支中的哪些提交不在另一个分支中?


180

我有两个分公司develnext。在开发中,我有或多或少的大量提交。其中一些提交是摘自樱桃的next。另外,我在next中添加了一些合并到的提交devel

现在我想看看缺少什么next,因此我可以在进行更改之前详细测试这些更改next。我的问题是,现在我该如何查看哪些提交devel在下一个提交中?



您的标题有点误导,因为您要比较的是两个分支的提示。我来到这里寻找解决方案,比较两个分支的两个特定的(不同的)提交
thebugfinder

Answers:


210

很少使用的命令git cherry向您显示尚未被挑选的提交。对于文档git cherry在这里,但是,总之,你应该能够做到:

git checkout devel
git cherry next

...并看到如下输出:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

开头的提交+将是您尚未挑选的next。在这种情况下,到目前为止,我只挑了一份承诺。您可能希望将-v参数添加到git cherry命令,以便它还输出每次提交的主题行。


太好了,这就是我所需要的。简短描述一下测试也很好,但是我可以编写脚本。
Sascha Effert

29
您不需要git checkout devel,您可以做git cherry next devel
罗宾·温斯洛

21
“可能要添加-v吗?没有樱桃-v就像ls没有樱桃-la; -J
Slipp D. Thompson

1
而且您不知道cherry标记或排除等效提交的方法,对吗? cherry似乎是一个管道命令,但没有(似乎)提供许多选项。对于我目前处于中间的情况,git cherry给了我误报,但@sehe git log --cherry-pick正确排除了先前选择/重新设置的提交。
Slipp D. Thompson

文档提供一个具体的例子:git-scm.com/docs/git-cherry#_concrete_example
AMS

107

另外,您可以使用

git log --left-right --graph --cherry-pick --oneline devel...next

获取分支之间未共享的实际不同提交的详细列表。

有效词是 --cherry-pick

--cherry-pick

当提交集受到对称差异限制时,请忽略任何与“另一端”的另一次提交引入相同更改的提交。例如,如果您有两个分支A和B,则通常只在它们的一侧列出所有提交的方法是--left-right,就​​像上面该选项说明中的示例一样。但是,它显示的是从另一个分支中精心挑选的提交(例如,“ 3rd on b”可能是从分支A中精心挑选的)。使用此选项,这样的提交对将从输出中排除。

更新如评论中所述,添加了git的最新版本--cherry-mark

--cherry-mark

类似于--chery-pick(请参见下文),但用=标记等效的提交而不是省略它们,而用+标记等效的提交。


1
这对我不起作用。我的git版本不知道--one-line,因此我将其删除。然后我不得不交换开发和下一步,它奏效了。非常好!
萨沙中Effert

@SaschaEffert:您不必切换devel和next(注意三个点,而不是两个)。这就是说,事情可能会有所不同,如果你使用了古老的git(?)的版本,但在这种情况下,你应该得到的三个点的REV-解析错误。
sehe 2011年

2
为了好玩,我计算出2006年7月添加了“ ...”(对称差异)rev-parse语法,并于2008年6月更新了其文档。开源的喜悦!
sehe 2011年

1
'gls --first-parent --cherry-mark --left-onlydevelop ... next',其中gls是我的git log别名,具有所有漂亮的格式。樱桃标记显示对樱桃的采摘和对非樱桃采摘的提交,但是对它们的标记不同。
angularsen 2014年

1
添加-不合并可能会更好
MervynYang

51

您可以尝试执行git log子集:

git log --oneline devel ^next

4
在我看来,这是最好的解决方案(@sehe的回答还显示了下一个落实中的提交不是在开发中-在OP的上下文中没有,但是在我的情况中-使用--left-only本来会更好)。但是,可以通过添加--no-merges省略任何合并提交(例如,将功能或修补程序分支(分别)合并到devel和next中合并)来进行一些改进。严格来说,当然,合并中的冲突解决方案可能会产生其他差异,但通常并非如此。该--no-merges选项也可以有效地应用于其他答案。
Alex Dupuy 2014年

27

怎么样

git log next..devel

结果类似于Byran的答案(不同的提交顺序),但是我们两个答案都会产生分支之间不同的提交,而只是显示一个分支中的内容,而不显示另一个分支中的内容。


4
如果您当前在第二个分支上,则也可以省略它。即git log next..
jmaxyz

btw'git log next..devel'与'git log devel..next'不同
Eugene Kaurov

1

要获取未集成到发行分支(下一个)中的提交列表,可以使用:

git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt

检查git-rev-list以获得更多信息。


此答案的命令缺少实际有问题的分支,即next...devel
Alex Dupuy 2014年

@AlexDupuy Yah,这是一个半定的答案。由于它也不是最简单的答案,也无法解释为什么这种方法会更好,因此我将其-1 -ing。
Slipp D. Thompson 2014年

-1

@Mark Longair在这里将其钉在了答案中,但我想补充一些其他见解。

相关,并回答有关如何拆分较大的Pull Request(PR)的问题,尤其是在压缩提交时,由于将master或多个master合并到feature_branch中是不切实际的

我的情况:
我做了feature_branch30次提交就大功告成,并在GitHub上打开了Pull Request(PR)将其合并到中master。布兰奇master改变了我身下的一吨,并收到了我feature_branch没有的200次提交。化解矛盾我也git checkout feature_branchgit merge master合并master的变成我的feature_branch。我选择了merge而不是使用rebase最新的Master,因此我只需要一次解决冲突,而不是潜在的30次(每次提交一次)。我不想先将30次提交压缩为1次,然后再基于最新的master因为这可能会清除PR中的GitHub评论评论历史记录。因此,我将master合并到我的功能分支中,并且一次解决了冲突。一切都好。但是,我的PR对我的同事来说太大了。我需要将其拆分。我去压缩了30个提交,哦,不!他们在哪?它们现在都与master最近的200次提交相互关联,因为我已合并master到我的文件中feature_branch!我该怎么办?

git cherry如果您想尝试git cherry-pick单个提交的用法:

git cherry 营救(某种)!

要查看其中所有feature_branch但不包含的所有提交,master我可以这样做:

git checkout feature_branch
git cherry master

或者,我可以从ANY分支检查提交,而无需确保像这样feature_branch先执行git cherry [upstream_branch] [feature_branch]。再次,这检查以查看哪些提交在其中feature_branch但不在upstream_branchmaster在这种情况下):

git cherry master feature_branch

添加-v还显示提交消息主题行:

git cherry -v master

用管道输送到“字数统计”“-行”(wc -l)计数有多少个提交:

git cherry master | wc -l

您可以将此计数与GithHub PR中显示的提交编号进行比较,以更好地了解git cherry实际工作情况。您还可以一一比较git散列,并查看它们git cherry与GitHub 之间的匹配。请注意,git cherry这不会计算您合并master到的任何合并提交feature_branch,但是GitHub WILL。因此,如果您发现计数之间的差异很小,请在GitHub PR提交页面上搜索单词“ merge”,您可能会发现这是罪魁祸首git cherry。例如:名为“将分支'master'合并到feature_branch中”的提交将显示在GitHub PR中,但在您运行时不会显示git cherry master feature_branch。这很好并且可以预期。

因此,现在,我有了一种方法,可以找出要添加到新功能分支上的差异以拆分该差异:我可以git cherry master feature_branch在本地使用,也可以查看GitHub PR中的提交。

壁球有什么帮助-如果只有我们可以壁球:

但是,拆分我的大差异的另一种方法是将我的所有30个提交压缩为一个,将其修补到新的功能分支上,软重置该修补程序提交,然后用于git gui逐个文件,逐个块地添加片段或逐行。获得一个子功能后,我可以提交添加的内容,然后签出一个新分支,添加更多内容,提交,签出一个新分支,依此类推,直到将我的大功能分解为几个子功能为止。问题是,我的30个提交与其他人等200个提交混由于我git merge master到我feature_branch,所以垫底因此不切实际的,因为我有过230个提交筛选一下以重新排序和壁球我30次的提交。

如何使用补丁文件作为壁球的替代品:

一种变通方法是简单地获取一个包含我所有30次提交的“等效”的补丁文件,将其补丁到master(新的子功能分支)的新fork上,然后从那里进行工作,如下所示:

git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master 
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch

现在,我已将30个提交的补丁全部应用在本地,但未登台且未提交。

现在用于git gui添加文件,块和/或行,并分解大的PR或“ diff”:

请注意,如果没有git gui,可以使用轻松在Ubuntu中安装它sudo apt install git-gui

现在git gui,我可以运行并开始添加文件,块和/或行(通过在git GUI程序中单击鼠标右键),然后将30个commit功能分支分成上述的子分支,反复添加,提交和分叉一个新的功能分支,重复此循环,直到所有更改都已添加到子功能分支,并且我的30提交功能被成功分解为3或4个子功能。我现在可以为这些子功能中的每个功能打开一个单独的PR,它们将使我的团队更容易查看。

参考文献:

  1. 从git仓库创建补丁或差异文件,并将其应用于另一个不同的git仓库

我今天需要参考此答案,但无法快速找到它。幸运的是,它有一个缺点,可以帮助我更轻松地找到它,因此,只需单击屏幕右上方的奖杯图标,即可显示我最近失去了2分的地方,然后单击该按钮将我带回到这里,我可以现在在这里参考我自己的答案!希望我不会再投票了,但是对投票者来说,多亏了意外帮助我的服务!
加布里埃尔·斯台普斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.