是否有git-merge --dry-run选项?


Answers:


811

如前所述,传递--no-commit标志,但是为了避免快速提交,也传递--no-ff,如下所示:

$ git merge --no-commit --no-ff $BRANCH

要检查分阶段的更改:

$ git diff --cached

您可以撤消合并,即使它是快速合并:

$ git merge --abort

51
很好,但是仍然会修改您的工作副本。如果您的回购是一个活生生的Web服务器,那么你可以在服务与冲突的文件。
dave1010

21
您不能真正进行合并而不影响工作副本。
mipadi

55
是的,但是类似git merge --only-if-there-wont-be-any-conflictsgit diff --show-conflicts <commit>会非常方便。可惜还不可能,还是我错过了什么?
dave1010'7

343
@ dave1010您永远不应在实时Web服务器上处理合并!!!那就是您的开发工具箱所用的!修复“ prod”分支,然后将其推送到真实的Web服务器。
jpswain 2011年

52
如果您在现场/生产服务器上工作,则除了git pull --ff-only
ThiefMaster 2012年

237

我只需要实现一种方法,该方法可以自动查找存储库与其远程数据库之间的冲突。该解决方案在内存中进行合并,因此不会触及索引或工作树。我认为这是解决此问题的最安全的方法。运作方式如下:

  1. 将远程获取到您的存储库。例如: git fetch origin master
  2. 运行git merge-base: git merge-base FETCH_HEAD master
  3. 运行git merge-tree:git merge-tree mergebase master FETCH_HEADmergebase是上一步中merge-base打印的十六进制ID)

现在假设您想将远程主服务器与本地主服务器合并,但是可以使用任何分支。git merge-tree将在内存中执行合并并将结果打印到标准输出。模式<<或的Grep >>。或者,您可以将输出打印到文件中并进行检查。如果您发现以“两个都更改”开头的行,则很可能会发生冲突。


41
恕我直言,这个答案被低估了,因为它是一种干净的解决方案,无需接触工作副本或索引。
sschuberth

23
顺便说一句,可以使用Linux控制台的git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
backtick

15
在.gitconfig中添加到[别名]中:dry =“!f(){git merge-tree`git merge-base $ 2 $ 1` $ 2 $ 1;}; f”#检查dev如何合并到master中:git dry开发人员
Noel

8
我最喜欢的新GIT系列:git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"太棒了!+100
鲁迪

4
在测试中,我发现grepping“两个都更改”标志合并,其中两个分支都修改了同一文件,即使它们不会导致合并冲突也是如此。为了只识别实际的冲突,我发现有必要使用grep来开始这样的冲突标记:+<<<<<<< .our,所以我使用grep表达式,例如grep -q '^+<* \.our$'
Guy

55

我对此的简单暴力解决方案是:

  1. 创建一个“ pre-master”分支(当然是来自master的)

  2. 将您想要的所有内容合并到该预掌握者中。
    然后,您可以看到合并过程是如何发生的,而无需接触master。

    • 将预母带合并为母带或
    • 将所有要发布的分支合并到母版中

无论如何,我会遵循@ orange80的建议。


5
我喜欢@akostajti解决方案,但这是另一个被低估的选择。实际上,我更喜欢防御并创建一个新的临时分支(当然,仅当我预计会发生冲突时,否则这将是一个过大的杀伤力),并且如果出现问题,只需将其删除即可。
jakub.g 2012年

1
dunno,无论这是否是“肮脏”的解决方案,但确实可以完成工作。我喜欢!(Y)
萨拉2015年

3
imo,这应该是公认的解决方案。它快速,简便,安全,可逆,直观,并且只要在开始之前没有任何未提交的更改,就不会有副作用。
Bob Ray

3
该解决方案告诉您不了解git如何工作。分支只是指针,您只在创建冗余指针。您有一种不好的感觉,您可能会以某种方式伤害分支合并,但是您不能这样做。git merge --abort如果发生冲突,git reset --hard HEAD~1合并或,您可以随时进行操作git reset --hard origin/master。创建另一个分支给您带来安全感,但是如果您了解git的工作原理,您将会了解它是放错了地方的恐惧。如果担心不更改工作副本,则不会提供任何解决方案。
Thibault D.

@ thibault-d考虑当您不以干净的分支开头时解决方案有多复杂。 git merge --no-commit如果可以快速转发合并,则不会中止合并。 git merge --abort如果合并,则不起作用。如果您想将其编写为脚本,那会很尴尬,因为git merge它没有足够好的错误代码来解释不同类型的冲突。使用新的分支可以防止损坏的脚本使您的存储库处于需要手动干预的状态。确保您不会失去任何东西。但是,以其他方式进行构建更容易。
Erik Aronesty,

47

取消与git的合并非常容易,您甚至不必担心试运行:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

编辑:如下面的注释中所述,如果您在工作目录或暂存区域中进行了更改,则可能需要在执行上述操作之前将其保存(否则它们将在git reset上述操作之后消失)


7
简单地检查合并是否将是快进(FF)只是检查列表的清单,git branch --contains HEAD甚至更直接,只需使用git merge --ff-only
Brian Phillips 2010年

7
git reset --hard是git具有的少数几个无回退信息删除命令之一,因此应格外小心。因此,-1
Kzqai 2012年

8
@Tchalvak仍然有reflog。
Kissaki

3
--dry-run不会“仅检查合并是否会快速进行”。它会返回合并的确切输出:文件,冲突等。ff是否不是很有趣,不是吗?
Rudie 2012年

3
怎么样git stash; git reset --hard?@BrianPhillips
耳语者

41

我为此做了一个别名,并且像一个吊饰一样工作,我这样做:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

现在我打电话

git mergetest <branchname>

找出是否有任何冲突。


辉煌!我保留这个。
qbert65536

28

只需将当前分支与远程分支进行比较,这将告诉您进行拉/合并时将要更改的内容。

#see diff between current master and remote branch
git diff master origin/master

1
有趣的主意。我将如何查看该输出并确定合并是否正常进行?
MatrixFrog 2011年

6
这不会告诉您是否会发生任何冲突...但是,它将使您大致了解如果执行拉/合并操作将会发生什么。
2011年

10
这只会告诉您两个分支之间的差异,而不会告诉您合并的结果是什么。这是一个重要的区别,因为在某些情况下,合并会根据提交的时间自动从不同分支中获取更改。因此,从本质上讲,执行差异可能会使您认为实际上更改了某些更改,合并过程将自动对较旧的更改进行较新的更改。希望有道理。
markquezada 2011年

3
要以@mirthlab的评论为基础,如果有人以前使用“我们的”合并策略(或其他一些手动合并修订程序)执行了合并,则diff与合并之间将存在显着差异。差异还会显示已被视为“合并”的差异。
2012年

21

我使用request-pull git命令这样做。它使您可以查看合并时可能发生的所有更改,但无需在本地或远程存储库上进行任何操作

例如,假设您想将一个名为“ feature-x”的分支合并到您的master分支中

git request-pull master origin feature-x

将向您显示将会发生的摘要(不执行任何操作):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

如果添加-p参数,您还将获得完整的补丁文本,就像在每个更改的文件上执行git diff一样。


3
通过在命令行选项中添加内容masterorigin操作,可以使这一点更加清晰,例如,如果我在本地,branch1并且想要request-pull在本地功能分支上进行操作branch2呢?我还需要origin吗?当然,人们总是可以阅读文档。
Ela782 2015年

可悲的是,该命令仅在Rev#2是分支名称的情况下才有效,不适用于哈希:/
Jared Grubb '18

20

我很惊讶没有人建议使用补丁。

假设您要测试从your_branch到的合并master(我假设您已master签出):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

这应该够了吧。

如果出现类似错误

error: patch failed: test.txt:1
error: test.txt: patch does not apply

这意味着补丁未成功,合并将产生冲突。没有输出意味着补丁是干净的,您将能够轻松合并分支


请注意,这实际上并不会改变您的工作树(当然,除了创建补丁文件之外,您可以放心地将其删除)。从git-apply文档中:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

请注意比我更精通/比git经验丰富的任何人:如果在这里输入错误,请告诉我,并且此方法的行为与常规合并不同。奇怪的是,这个问题已经存在了8年以上,没有人会提出这个看似明显的解决方案。


此方法是该问题的可接受答案并且注释中有一些警告,例如“ git无法使用“递归”合并策略”和“补丁文件为新文件提供了错误”。否则,看起来很棒。
neno

1
不创建临时补丁文件的更短方法:git diff master your_branch | git apply --check
ks1322 '18

9

这可能很有趣:从文档中:

如果您尝试了导致复杂冲突的合并并想重新开始,则可以使用git merge --abort恢复。

但是,您也可以采用幼稚(但很慢)的方法:

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(注意:仅克隆到/ tmp就无法工作,您需要一个副本,以确保未提交的更改不会冲突)。


2
如果您只需要一把锤子... :) +1
kaiser 2014年

干净的副本可以与获得cp -r repository/.git /tmp/repository/.gitcd /tmp/repositorygit reset --hardgit add --allgit reset --hard(好措施), git status(检查它的清洁)。
ADTC '17

8

我知道这是一个古老的问题,但这是第一个出现在Google搜索中的问题。

合并时,Git引入了--ff-only选项。

来自:http : //git-scm.com/docs/git-merge


--ff仅

拒绝合并并以非零状态退出,除非当前的HEAD已经是最新的,或者可以将合并解析为快进。

这样做会尝试合并并快速转发,如果无法合并,则会中止并提示您无法执行快速转发,但不会影响您的工作分支。如果它可以快进,那么它将在您的工作分支上执行合并。此选项在上也可用git pull。因此,您可以执行以下操作:

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
如果可以通过快进完成合并,那将完成合并,这不是我在原始问题中想要的。我认为已接受的答案还有另一半可以解决。
奥托(Otto)

确实,花哨的git提示消除了我对这种事情的需要。
奥托(Otto)

2
真的不一样。以非零状态退出,因为合并无法解析,因为快进并不意味着存在冲突。这仅表示历史有所分歧,必须进行合并提交。
ADTC

7

我使用git log从master分支查看功能分支上的更改

git log does_this_branch..contain_this_branch_changes

例如-查看已/未合并到master的功能分支中的提交:

git log master..feature_branch

3

如果要从B快进到A,则必须确保git log B..A不显示任何内容,即A没有B没有的内容。但是,即使B..A拥有某些东西,您仍然可以在没有冲突的情况下进行合并,因此上面显示了两件事:将会有一个快进,因此您不会发生冲突。


2

我的解决方案是向后合并。

与其将您的分支合并到远程“目标”分支中,不如将该分支合并到您的分支中。

git checkout my-branch
git merge origin/target-branch

您将看到是否存在任何冲突,并可以计划如何解决它们。

之后,您可以通过git中止合并merge --abort,或者(如果没有任何冲突并且发生了合并)通过以下方式回滚到先前的提交git reset --hard HEAD~1


-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.