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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7566416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 11:56:38  来源:igfitidea点击:

How to see which commits in one branch aren't in the other?

git

提问by Sascha Effert

I have two branches develand next. In devel I have a more or less huge amount of commits. Some of the commits are cherry picked in next. Also I added some commits to next which are merged to devel.

我有两个分支develnext. 在开发中,我或多或少有大量的提交。一些提交是在next. 我还向 next 添加了一些提交,这些提交合并到devel.

Now I would like to see what is missing in next, so I can test the changes in detail before bringing them to next. My question is now, how can I see which commits are in develbut not in next?

现在我想看看缺少什么next,所以我可以在将它们带到next. 我现在的问题是,我怎样才能看到哪些提交在devel但不在下一个?

回答by Mark Longair

The little-used command git cherryshows you the commits which haven't yet been cherry-picked. The documentation for git cherryis here, but, in short, you should just be able to do:

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

git checkout devel
git cherry next

... and see output a bit like this:

...并看到输出有点像这样:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

The commits that begin with +will be the ones that you haven't yetcherry-picked into next. In this case, I'd only cherry-picked one commit so far. You might want to add the -vparameter to the git cherrycommand, so that it also outputs the subject line of each commit.

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

回答by sehe

Also, you can use

此外,您可以使用

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

to get a nice list of actualdifferent commits not shared between the branches.

获得一个很好的列表,列出了分支之间未共享的实际不同提交。

The operative word is --cherry-pick

操作词是 --cherry-pick

--cherry-pick

Omit any commit that introduces the same change as another commit on the "other side" when the set of commits are limited with symmetric difference. For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right, like the example above in the description of that option. It however shows the commits that were cherry-picked from the other branch (for example, "3rd on b" may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.

--cherry-pick

当提交集受限于对称差异时,省略任何引入与“另一端”的另一个提交相同的更改的提交。例如,如果您有两个分支,A 和 B,通常只列出其中一侧的所有提交的方法是使用 --left-right,就​​像上面该选项描述中的示例一样。然而,它显示了从另一个分支中挑选出来的提交(例如,“b 上的第三个”可能是从分支 A 中挑选出来的)。使用此选项,此类提交对将从输出中排除。

UpdateAs mentioned in a comment, recent versions of git added --cherry-mark:

更新正如评论中提到的,最近版本的 git 添加了--cherry-mark

--cherry-mark

Like --cherry-pick (see below) but mark equivalent commits with = rather than omitting them, and inequivalent ones with +.

--cherry-mark

像--cherry-pick(见下文),但用= 标记等效提交而不是省略它们,用+ 标记不等效的提交。

回答by Bryan Buckley

You might could try doing git log subsets:

你可以尝试做 git log 子集:

git log --oneline devel ^next

回答by justingordon

How about

怎么样

git log next..devel

Result is similar to Byran's answer (different order of commits) but both of our answers will produce commits that are different between the branches, rather just showing what's in one branch and not in the other.

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

回答by Mihai

To get the list of commits that were not integrated into the release branch (next) you may use:

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

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

Check git-rev-listfor more info.

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

回答by Gabriel Staples

@Mark Longair nailed it in his answer here, but I'd like to add some additional insight.

@Mark Longair 在他的回答中指出了这一点,但我想补充一些额外的见解。

Related, and answering the question of how to break up a large Pull Request (PR), especially when squashing your commits is impractical due to one or more merges of master into your feature_branch

相关,并回答有关如何分解大型拉取请求 (PR) 的问题,尤其是当由于一个或多个 master 合并到您的 feature_branch 而压缩您的提交是不切实际的时

My situation:
I made a big feature_branchwith 30 commits and opened a Pull Request (PR) on GitHub to merge it into master. Branch masterchanged a ton underneath me, and received 200 commits my feature_branchdidn't have. To resolve conflicts I did git checkout feature_branchand git merge masterto merge master's changes into my feature_branch. I chose to mergerather than rebaseonto latest master so I would have to resolve conflicts only one single time instead of potentially 30 times (once for each of my commits). I didn't want to squash my 30 commits into 1 first and then rebase onto the latest masterbecause that might wipe away GitHub review comment history in the PR. So, I merged master into my feature branch and resolved conflicts 1 single time. All was well. My PR, however, was too big for my colleagues to review. I needed to split it up. I went to squash my 30 commits and OH NO! WHERE ARE THEY? THEY ARE ALL INTERMINGLED WITH master's 200 recent commits now because I merged masterinto my feature_branch! WHAT DO I DO?

我的情况:
我做了feature_branch30 次提交,并在 GitHub 上打开了一个拉取请求 (PR) 以将其合并到master. Branchmaster在我下面改变了很多,并收到了 200 个我feature_branch没有的提交。化解矛盾我也git checkout feature_branchgit merge master合并master的变成我的feature_branch。我选择了merge而不是rebase最新的 master,所以我只需要解决一次冲突,而不是可能的 30 次(每次提交一次)。我不想先把我的 30 个提交压缩成 1 个,然后再重新调整到最新的master因为这可能会清除 PR 中的 GitHub 评论评论历史。因此,我将 master 合并到我的功能分支并解决了 1 次冲突。一切都好。然而,我的 PR 太大了,我的同事们无法。我需要把它分开。我去压缩我的 30 次提交,哦不!他们在哪里?它们现在都与master200 个最近的提交混合在一起,因为我合并master到了我的feature_branch! 我该怎么办?

git cherryusage in case you want to try to git cherry-pickindividual commits:

git cherry如果您想尝试git cherry-pick单独提交,请使用:

git cherryto the rescue (sort of)!

git cherry拯救(有点)!

To see all the commits that are in feature_branchbut NOT in masterI can do:

要查看所有在feature_branch但不在的提交,master我可以执行以下操作:

git checkout feature_branch
git cherry master

OR, I can check commits from ANY branch withOUT ensuring I'm on feature_branchfirst by doing git cherry [upstream_branch] [feature_branch], like this. Again, this checks to see which commits ARE in feature_branchbut are NOT in upstream_branch(masterin this case):

或者,我可以检查来自任何分支的提交,而无需确保我feature_branch首先通过执行git cherry [upstream_branch] [feature_branch],像这样。同样,这会检查哪些提交在feature_branch但不在upstream_branchmaster在这种情况下):

git cherry master feature_branch

Adding -valso shows the commit message subject lines:

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

git cherry -v master

Piping to "word count" "-lines" (wc -l) counts how many commits there are:

管道到“字数”“-lines”(wc -l)计算有多少提交:

git cherry master | wc -l

You can compare this count against the commit number shown in your GithHub PR to feel better about knowing git cherryreally is working. You can also compare the git hashes one by one and see they match between git cherryand GitHub. Note that git cherrywill NOT count any merge commits where you merged masterinto feature_branch, but GitHub WILL. So if you see a small discrepancy in the count, search the GitHub PR commit page for the word "merge" and you'll probably see that's the culprit which is not showing up in git cherry. Ex: a commit titled "Merge branch 'master' into feature_branch"will show up in the GitHub PR but not when you run git cherry master feature_branch. This is fine and expected.

您可以将此计数与 GithHub PR 中显示的提交数量进行比较,以便更好地了解git cherry确实有效。您还可以一一比较 git 哈希,看看它们在git cherryGitHub之间是否匹配。请注意,git cherry不会计算您合并master到 中的任何合并提交feature_branch,但 GitHub 会。因此,如果您看到计数中的小差异,请在 GitHub PR 提交页面中搜索“合并”一词,您可能会发现这是没有出现在git cherry. 例如:标题为“Merge branch 'master' into feature_branch”的提交将显示在 GitHub PR 中,但不会在您运行git cherry master feature_branch. 这很好,也符合预期。

So, now I have a means of finding out which diffs I may want to cherry-pick onto a fresh feature branch to split up this diff: I can use git cherry master feature_branchlocally, or look at the commits in the GitHub PR.

所以,现在我有办法找出哪些差异我可能想要挑选到一个新的功能分支上来拆分这个差异:我可以git cherry master feature_branch在本地使用,或者查看 GitHub PR 中的提交。

How squashing could help--if only we could squash:

挤压有什么帮助——如果我们能挤压:

An alternative, however, to split up my big diff is to squash all 30 of my commits into one, patch that onto a new feature branch, soft reset the patch commit, then use git guito add pieces file by file, chunk by chunk, or line by line.Once I get one sub-feature, I can commit what I've added then check out a new branch, add some more, commit, check out a new branch, etc, until I have my big feature broken out into several sub-features. The problem is that my 30 commits are intermingled with the other 200 commits from other people due to my git merge masterinto my feature_branch, so rebasing is therefore impractical, as I'd have to sift through 230 commits to re-order and squash my 30 commits.

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

How to use a patch file as a much easier replacement for squashing:

如何使用补丁文件来更轻松地替代压缩:

A work-around is to simply obtain a patch filecontaining a "squash-equivalent" of all 30 of my commits, patch it onto a new fork of master(a new sub-feature-branch), and work from there, as follows:

一种解决方法是简单地获取一个补丁文件,其中包含我所有 30 个提交的“壁球等效”,将其修补到master(一个新的子功能分支)的新分支上,然后从那里开始工作,如下所示:

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

Now I have my 30-commit patch all applied locally, but unstaged and uncommitted.

现在我的 30-commit 补丁全部应用在本地,但未暂存和未提交。

Now use git guito add files, chunks, and/or lines and break up your big PR or "diff":

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

Note that if you don't have git gui, you can easily install it in Ubuntu with sudo apt install git-gui.

请注意,如果您没有git gui,您可以使用sudo apt install git-gui.

I can now run git guiand start adding files, chunks, and/or lines (by right-clicking in the git GUI program), and break up the 30 commit feature branch into sub branches as described just above, repeatedly adding, committing, then forking a new feature branch and repeating this cycle until all changes have been added to a sub-feature-branch and my 30-commit feature is successfully broken up into 3 or 4 sub-features. I can open up a separate PR for each of these sub-features now, and they will be easier for my team to review.

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

References:

参考:

  1. Create patch or diff file from git repository and apply it to another different git repository
  1. 从 git 存储库创建补丁或差异文件并将其应用到另一个不同的 git 存储库