我有一个 git 分支(例如主线),我想合并到另一个开发分支。还是我?
为了决定我是否真的想合并这个分支,我想看看合并将做什么的某种预览。最好能够查看正在应用的提交列表。
到目前为止,我能想到的最好的方法是merge --no-ff --no-commit
, 然后diff HEAD
.
git log ..otherbranch
git diff ...otherbranch
gitk ...otherbranch
空字符串意味着HEAD
,所以这就是为什么只是..otherbranch
而不是HEAD..otherbranch
。
两个点与三个点对于 diff 的含义与列出修订的命令(log、gitk 等)的含义略有不同。对于 log 和其他人来说,两个点 ( a..b
) 表示所有在b
但不在其中的内容a
,三个点 ( a...b
) 表示仅在a
or之一中的所有内容b
。但是 diff 适用于两个修订版,并且由两个点 ( ) 表示的更简单的情况是与toa..b
的简单差异,三个点 ( ) 表示共同祖先和( ) 之间的差异。a
b
a...b
b
git diff $(git merge-base a b)..b
我发现最适合我的解决方案是执行合并并在有冲突时中止它。这种特殊的语法对我来说感觉干净简单。这是下面的策略2。
但是,如果您想确保不会弄乱当前分支,或者无论是否存在冲突,您还没有准备好合并,只需创建一个新的子分支并将其合并:
git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch
这样,如果您只想查看冲突是什么,您可以简单地丢弃临时分支。您无需费心“中止”合并,您可以回到您的工作 - 只需再次签出“mybranch”,您的分支中不会有任何合并代码或合并冲突。
这基本上是一个试运行。
git checkout mybranch
git merge some-other-branch
如果 git 报告冲突(并且仅当存在冲突时),您可以执行以下操作:
git merge --abort
如果合并成功,则不能中止它(只能重置)。
如果您还没有准备好合并,请使用上述更安全的方式。
[编辑:2016 年 11 月 - 我将策略 1 换成 2,因为似乎大多数人都在寻找“安全的方式”。策略 2 现在更像是一个说明,如果合并存在您尚未准备好处理的冲突,您可以简单地中止合并。请记住,如果阅读评论!]
这里的大多数答案要么需要一个干净的工作目录和多个交互式步骤(不利于脚本编写),要么不适用于所有情况,例如过去的合并已经将一些未完成的更改带入您的目标分支,或者樱桃挑选做相同的。
master
要真正了解如果合并到分支中会发生什么变化develop
,现在:
git merge-tree $(git merge-base master develop) master develop
由于它是一个管道命令,它不会猜测您的意思,您必须明确。它也不会为输出着色或使用您的寻呼机,因此完整的命令将是:
git merge-tree $(git merge-base master develop) master develop | colordiff | less -R
— https://git.seveas.net/previewing-a-merge-result.html
(感谢大卫诺明顿的链接)
PS:
如果您遇到合并冲突,它们将在输出中显示常见的冲突标记,例如:
$ git merge-tree $(git merge-base a b ) a b
added in both
our 100644 78981922613b2afb6025042ff6bd878ac1994e85 a
their 100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
a
+=======
+b
+>>>>>>> .their
用户@dreftymac 提出了一个很好的观点:这使得它不适合编写脚本,因为你不能轻易地从状态代码中捕捉到它。冲突标记可能会因情况而异(删除与修改等),这也使得 grep 变得困难。谨防。
如果你像我一样,你正在寻找等同于svn update -n
. 以下似乎可以解决问题。请注意,请务必先进行操作,git fetch
以便您的本地存储库有适当的更新来进行比较。
$ git fetch origin
$ git diff --name-status origin/master
D TableAudit/Step0_DeleteOldFiles.sh
D TableAudit/Step1_PopulateRawTableList.sh
A manbuild/staff_companies.sql
M update-all-slave-dbs.sh
或者如果你想要从你的头到遥控器的差异:
$ git fetch origin
$ git diff origin/master
与建议“合并然后中止”的顶级解决方案相比,IMO 这个解决方案更容易且更不容易出错(因此风险也更小)。
添加到现有答案中,可以创建一个别名以在合并之前显示差异和/或日志。许多答案省略了fetch
在“预览”合并之前首先要做的事情;这是将这两个步骤合二为一的别名(模拟类似于 mercurial 的hg incoming
/ outgoing
)
因此,在“ git log ..otherbranch
”的基础上,您可以将以下内容添加到~/.gitconfig
:
...
[alias]
# fetch and show what would be merged (use option "-p" to see patch)
incoming = "!git remote update -p; git log ..@{u}"
为了对称,以下别名可用于显示在推送之前已提交和将要推送的内容:
# what would be pushed (currently committed)
outgoing = log @{u}..
然后你可以运行“ git incoming
”来显示很多变化,或者“ git incoming -p
”来显示补丁(即“diff”),“ git incoming --pretty=oneline
”,以获得简洁的总结,等等。然后你可以(可选地)运行“ git pull
”来实际上合并。(不过,既然您已经提取了,可以直接进行合并。)
同样,“ git outgoing
”显示如果您要运行“”会推送什么git push
。
如果您已经获取了更改,我最喜欢的是:
git log ...@{u}
我相信这需要 git 1.7.x。该 @{u}
符号是上游分支的“速记”,因此它比git log ...origin/master
.
注意:如果您使用 zsh 和扩展的 glog 东西,您可能必须执行以下操作:
git log ...@\{u\}
git log currentbranch..otherbranch
如果您进行合并,将为您提供将进入当前分支的提交列表。提供有关提交详细信息的 log 通常参数将为您提供更多信息。
git diff currentbranch otherbranch
将为您提供将成为一个的两个提交之间的差异。这将是一个差异,为您提供将要合并的所有内容。
这些会有帮助吗?
没有以一种丢弃的方式实际执行合并(参见 Kasapo 的回答),似乎没有一种可靠的方式来看待这一点。
话虽如此,这是一种稍微接近的方法:
git log TARGET_BRANCH...SOURCE_BRANCH --cherry
这可以公平地表明哪些提交将进入合并。要查看差异,请添加-p
. 要查看文件名,请添加--raw
, --stat
, --name-only
, 中的任何一个--name-status
。
该git diff TARGET_BRANCH...SOURCE_BRANCH
方法的问题(请参阅 Jan Hudec 的答案)是,如果您的源分支包含交叉合并,您将看到目标分支中已有更改的差异。
拉取请求 - 我已经使用了大部分已经提交的想法,但我也经常使用的一个是(特别是如果它来自另一个开发者)做一个拉取请求,它提供了一种方便的方法来审查合并中的所有更改,然后再进行地方。我知道那是 GitHub 而不是 git,但它确实很方便。
也许这可以帮助你? git-diff-tree - 比较通过两个树对象找到的 blob 的内容和模式
我不想使用 git merge 命令作为查看冲突文件的前导。我不想进行合并,我想在合并之前找出潜在的问题——自动合并可能对我隐藏的问题。我一直在寻找的解决方案是如何让 git 吐出两个分支中已更改的文件列表,这些文件将在未来合并在一起,相对于某个共同的祖先。一旦我有了那个列表,我就可以使用其他文件比较工具来进一步查找。我已经搜索了多次,但我仍然没有在本机 git 命令中找到我想要的内容。
这是我的解决方法,以防它帮助其他人:
在这种情况下,我有一个名为 QA 的分支,自上次生产版本以来,它发生了许多变化。我们最后的生产版本标记为“15.20.1”。我有另一个名为 new_stuff 的开发分支,我想将它合并到 QA 分支中。QA 和 new_stuff 都指向“遵循”(由 gitk 报告)15.20.1 标签的提交。
git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files
以下是一些关于为什么我对针对这些特定文件感兴趣的讨论:
https://softwareengineering.stackexchange.com/questions/199780/how-far-do-you-trust-automerge
我试过这个东西来查看 Visual Studio 代码的变化。
从 dev 创建一个临时分支。然后将更改文件的分支与 --no-ff --no-commit 标志合并。
git checkout dev
git checkout -b feature_temp
git merge feature --no-ff --no-commit
功能分支的更改文件将反映在 feature_temp 分支中。