465

我有一个 git 分支(例如主线),我想合并到另一个开发分支。还是我?

为了决定我是否真的想合并这个分支,我想看看合并将做什么的某种预览。最好能够查看正在应用的提交列表。

到目前为止,我能想到的最好的方法是merge --no-ff --no-commit, 然后diff HEAD.

4

12 回答 12

461
  • git log ..otherbranch
    • 将合并到当前分支的更改列表。
  • git diff ...otherbranch
    • 从共同祖先(合并基础)到将要合并的内容的头部的差异。注意三个点,与两个点相比,它们具有特殊的含义(见下文)。
  • gitk ...otherbranch
    • 自上次合并以来分支的图形表示。

空字符串意味着HEAD,所以这就是为什么只是..otherbranch而不是HEAD..otherbranch

两个点与三个点对于 diff 的含义与列出修订的命令(log、gitk 等)的含义略有不同。对于 log 和其他人来说,两个点 ( a..b) 表示所有在b但不在其中的内容a,三个点 ( a...b) 表示仅在aor之一中的所有内容b。但是 diff 适用于两个修订版,并且由两个点 ( ) 表示的更简单的情况是与toa..b的简单差异,三个点 ( ) 表示共同祖先和( ) 之间的差异。aba...bbgit diff $(git merge-base a b)..b

于 2011-04-28T12:02:46.703 回答
326

我发现最适合我的解决方案是执行合并并在有冲突时中止它。这种特殊的语法对我来说感觉干净简单。这是下面的策略2

但是,如果您想确保不会弄乱当前分支,或者无论是否存在冲突,您还没有准备好合并,只需创建一个新的子分支并将其合并:

策略1:安全的方式——合并一个临时分支:

git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch

这样,如果您只想查看冲突是什么,您可以简单地丢弃临时分支。您无需费心“中止”合并,您可以回到您的工作 - 只需再次签出“mybranch”,您的分支中不会有任何合并代码或合并冲突。

这基本上是一个试运行。

策略 2:当你确定要合并时,但前提是没有冲突

git checkout mybranch
git merge some-other-branch

如果 git 报告冲突(并且当存在冲突时),您可以执行以下操作:

git merge --abort

如果合并成功,则不能中止它(只能重置)。

如果您还没有准备好合并,请使用上述更安全的方式。

[编辑:2016 年 11 月 - 我将策略 1 换成 2,因为似乎大多数人都在寻找“安全的方式”。策略 2 现在更像是一个说明,如果合并存在您尚未准备好处理的冲突,您可以简单地中止合并。请记住,如果阅读评论!]

于 2015-05-28T20:49:01.823 回答
19

这里的大多数答案要么需要一个干净的工作目录和多个交互式步骤(不利于脚本编写),要么不适用于所有情况,例如过去的合并已经将一些未完成的更改带入您的目标分支,或者樱桃挑选做相同的。

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 变得困难。谨防。

于 2019-02-28T13:35:41.130 回答
18

如果你像我一样,你正在寻找等同于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 这个解决方案更容易且更不容易出错(因此风险也更小)。

于 2012-11-01T22:27:11.930 回答
6

添加到现有答案中,可以创建一个别名以在合并之前显示差异和/或日志。许多答案省略了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

于 2012-09-05T06:33:22.157 回答
6

如果您已经获取了更改,我最喜欢的是:

git log ...@{u}

我相信这需要 git 1.7.x。该 @{u}符号是上游分支的“速记”,因此它比git log ...origin/master.

注意:如果您使用 zsh 和扩展的 glog 东西,您可能必须执行以下操作:

git log ...@\{u\}
于 2013-02-03T18:50:02.143 回答
3

git log currentbranch..otherbranch如果您进行合并,将为您提供将进入当前分支的提交列表。提供有关提交详细信息的 log 通常参数将为您提供更多信息。

git diff currentbranch otherbranch将为您提供将成为一个的两个提交之间的差异。这将是一个差异,为您提供将要合并的所有内容。

这些会有帮助吗?

于 2011-04-28T11:46:09.250 回答
3

没有以一种丢弃的方式实际执行合并(参见 Kasapo 的回答),似乎没有一种可靠的方式来看待这一点。

话虽如此,这是一种稍微接近的方法:

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

这可以公平地表明哪些提交将进入合并。要查看差异,请添加-p. 要查看文件名,请添加--raw, --stat, --name-only, 中的任何一个--name-status

git diff TARGET_BRANCH...SOURCE_BRANCH方法的问题(请参阅 Jan Hudec 的答案)是,如果您的源分支包含交叉合并,您将看到目标分支中已有更改的差异。

于 2016-04-19T05:00:07.693 回答
3

拉取请求 - 我已经使用了大部分已经提交的想法,但我也经常使用的一个是(特别是如果它来自另一个开发者)做一个拉取请求,它提供了一种方便的方法来审查合并中的所有更改,然后再进行地方。我知道那是 GitHub 而不是 git,但它确实很方便。

于 2017-04-06T13:11:21.080 回答
1

也许这可以帮助你? git-diff-tree - 比较通过两个树对象找到的 blob 的内容和模式

于 2011-04-28T11:12:00.177 回答
1

我不想使用 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

以下是一些关于为什么我对针对这些特定文件感兴趣的讨论:

我如何信任 Git 合并?

https://softwareengineering.stackexchange.com/questions/199780/how-far-do-you-trust-automerge

于 2015-10-21T19:27:45.540 回答
1

我试过这个东西来查看 Visual Studio 代码的变化。

从 dev 创建一个临时分支。然后将更改文件的分支与 --no-ff --no-commit 标志合并。

git checkout dev 
git checkout -b feature_temp 
git merge feature --no-ff --no-commit

功能分支的更改文件将反映在 feature_temp 分支中。

于 2021-09-15T06:55:26.467 回答