有没有git-merge --dry-run选项?

Ott*_*tto 681 git git-merge

我正在合并一个可能有很多冲突的远程分支.我怎么知道它是否会有冲突?

我没有看到像什么--dry-rungit-merge.

mip*_*adi 751

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

$ git merge --no-commit --no-ff $BRANCH
Run Code Online (Sandbox Code Playgroud)

要检查分阶段的变化:

$ git diff --cached
Run Code Online (Sandbox Code Playgroud)

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

$ git merge --abort
Run Code Online (Sandbox Code Playgroud)

  • @ dave1010你永远不应该在实时网络服务器上处理合并!这就是您的开发盒所针对的!修复"prod"分支,然后将其推送到真正的网络服务器. (330认同)
  • 这很棒,但仍会修改您的工作副本.如果您的repo是实时网络服务器,那么您可能正在提供有冲突的文件. (49认同)
  • 是的,但是像`git merge --only-if-there-wont-be-any-conflicts`或`git diff --show-conflicts <commit>`这样的东西真的很方便.羞耻它还不可能,或者我错过了什么? (49认同)
  • 如果你在一个实时/生产服务器上工作,除了`git pull --ff-only`你永远不想做任何事情! (49认同)
  • 在不影响工作副本的情况下,您无法真正进行合并. (21认同)
  • @donquixote意外地推动了局部变化并不像以前那样容易出错; 默认情况下,任何最近的(c.2010)版本的git都会拒绝"推送"到签出的分支/非裸仓库.http://stackoverflow.com/q/2816369/404960 (4认同)
  • akostajti下面的方法(http://stackoverflow.com/a/6283843/116596)要好得多,不需要弄乱你的工作副本. (4认同)
  • 如果可以合并,答案应该提到退出状态为"0". (4认同)
  • 凉爽的!但我该如何撤销这个操作呢?它说“所有冲突都已解决,但您仍在合并”。调用 `git checkout .` 不会将文件恢复到合并前状态。 (3认同)
  • NVM.弄清楚了.你叫`git merge --abort` (2认同)
  • @losaliens:自动提交快进合并。由于目的是在不提交合并的情况下检查合并的结果,因此需要使用“--no-ff”来防止自动提交合并。(在最新版本的 Git 中没有必要。) (2认同)

小智 223

我只需要实现一个自动查找存储库与其远程存储库之间冲突的方法.此解决方案在内存中进行合并,因此它不会触及索引,也不会触及工作树.我认为这是解决这个问题最安全的方法.以下是它的工作原理:

  1. 将远程数据库提取到存储库.例如: git fetch origin master
  2. 运行git merge-base: git merge-base FETCH_HEAD master
  3. 运行git合并树:git merge-tree mergebase master FETCH_HEAD(mergebase是mergebase在先前步骤中打印的十六进制ID)

现在假设您要将远程主服务器与本地主服务器合并,但您可以使用任何分支.git merge-tree将在内存中执行合并并将结果打印到标准输出.Grep的模式<<>>.或者您可以将输出打印到文件并检查.如果你找到一条以"两者都改变​​"开头的行,那么很可能会发生冲突.

  • 这个答案被低估了,恕我直言,因为它是一个干净的解决方案,没有触及工作副本或索引. (38认同)
  • 顺便说一句,第2步和第3步可以合并为一步,使用Linux控制台的反引号操作符,它就地评估其内容:`git merge-tree \`git merge-base FETCH_HEAD master \`FETCH_HEAD master` (22认同)
  • 添加到.gitconfig中的[alias]:dry ="!f(){git merge-tree \`git merge-base $ 2 $ 1 \`$ 2 $ 1;}; f"#check如何将dev合并到master中: git干开发大师 (14认同)
  • 我最喜欢的GIT系列:``git merge-tree`git merge-base clieop master` clieop master | grep -A3"两者都改变​​了"``简直太棒了!+100 (8认同)
  • 在测试中,我发现在两个分支中的'更改'标记的合并,两个分支修改同一个文件,即使它们不会导致合并冲突.为了识别实际的冲突我发现有必要grep这样开始的冲突标记:`+ <<<<<<<<our`,所以我使用grep表达式,如`grep -q'^ + <*\.我们$'` (4认同)
  • 好的!这是我目前最喜欢的:`git merge-tree $(git merge-base $1 $2) $1 $2 | sed -n '/+&lt;&lt;&lt;&lt;&lt;&lt;&lt; .our/,/+&gt;&gt;&gt;&gt;&gt;&gt;&gt; .their/p;/^在两个/{n;N;N;s/^/#/中均已更改毫克;p}' | cdiff`。它提取“两行均已更改”的行以及冲突的部分。 (3认同)
  • 这个答案几乎是好的。不幸的是,如果发生冲突,一个分支更改了一个文件而另一个分支删除了同一个文件,则它不起作用。 (2认同)
  • IMNSHO,此功能应该在新的“git merge --dry-run”标志下**上游**。 (2认同)

小智 51

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

  1. 创建一个"预主"分支(当然是硕士)

  2. 将您想要的所有内容合并到此预主程序中.
    然后你可以看到合并是如何发生而不触及主人.

    • 将pre-master合并为master OR
    • 将所有想要释放的分支合并为主人

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

  • 我喜欢@akostajti解决方案,但这是另一个被低估的选择.事实上,我更喜欢防守并创建一个新的临时分支(当然只有当我预料到冲突时,否则它会是一种过度杀伤),如果出现问题,只需将其删除即可. (5认同)
  • 这个解决方案告诉你不明白 git 是如何工作的。分支只是指针,您只是在创建一个冗余指针。你有一种不好的感觉,你可能会以某种方式伤害你的分支合并,但你不能。如果有冲突,你总是可以执行 `git merge --abort`,如果有合并,你可以执行 `git reset --hard HEAD~1` 或 `git reset --hard origin/master`。创建另一个分支会给你一种安全感,但如果你了解了 git 是如何工作的,你就会明白这是一种错位的恐惧。当担心不更改工作副本时,这没有提供解决方案。 (3认同)
  • 不知道这是否是一个“肮脏”的解决方案,但它确实有效。我喜欢!(是) (2认同)
  • imo,这应该是公认的解决方案。它快速,简便,安全,可逆,直观,并且只要在开始之前没有任何未提交的更改,就不会有副作用。 (2认同)
  • @thibault-d 想想当您不从干净的分支开始时,解决方案有多么复杂。如果可以快进,`git merge --no-commit` 不会中止合并。如果合并了,`git merge --abort` 将不起作用。如果你想把它写成一个脚本,那就很尴尬了,因为 `git merge` 不会用足够好的错误代码来回复来解释不同类型的冲突。使用新分支可以防止损坏的脚本使您的存储库处于需要手动干预的状态。当然你不能失去任何东西。但以其他方式构建会更容易。 (2认同)

Bri*_*ips 47

撤消与git的合并是如此简单,你甚至不应该担心干运行:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world
Run Code Online (Sandbox Code Playgroud)

编辑:如下面的评论所述,如果您的工作目录或临时区域有变化,您可能希望在执行上述操作之前隐藏它们(否则它们将在git reset上面的内容后消失)

  • @Tchalvak还有reflog. (8认同)
  • 简单地检查合并是否快进(FF)是检查`git branch --contains HEAD`列表甚至更直接的问题,只需使用`git merge --ff-only` (7认同)
  • git reset --hard是git拥有的为数不多的无信息删除命令之一,因此应谨慎使用.因此,-1 (6认同)
  • `--dry-run`不会"简单地检查合并是否会快进".它将返回合并的确切输出:文件,冲突等.是否ff不是真的有趣,是吗? (3认同)
  • 怎么样`git stash; git reset --hard`?@BrianPhillips (3认同)
  • `git reset` 会丢弃任何本地未提交的更改。这是危险的,应该是最后的手段。 (2认同)

Oko*_*000 37

我为这样做了一个别名并且像魅力一样,我这样做:

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

现在我打电话

git mergetest <branchname>
Run Code Online (Sandbox Code Playgroud)

找出是否有任何冲突.


tim*_*imh 28

只是将当前分支与远程分支区分开来,这将告诉您在执行拉/合并时会发生什么变化.

#see diff between current master and remote branch
git diff master origin/master
Run Code Online (Sandbox Code Playgroud)

  • 这只会告诉你两个分支之间的区别,它不会告诉你合并的结果是什么.这是一个重要的区别,因为合并在某些情况下会根据提交时间自动从不同的分支中进行更改.所以从本质上讲,做一个差异可能会让你认为你的一些变化会在现实中被还原,合并过程会自动对旧版本进行更新.希望有道理. (10认同)
  • 这不会告诉你是否会发生任何冲突......但它会让你大致了解如果你做了拉/合并会发生什么. (6认同)
  • 要构建@mirthlab的评论,如果有人先前使用"我们的"合并策略(或其他一些手动合并修正)进行合并,那么差异和合并之间会有显着差异; 差异还会显示已被计为"合并"的差异. (3认同)
  • 有趣的想法。我将如何查看该输出并确定合并是否会起作用? (2认同)

Arn*_*udR 20

我使用request-pull git命令来执行此操作.它允许您查看合并时可能发生的每个更改,但不在本地或远程存储库上执行任何操作.

例如,假设您要将名为"feature-x"的分支合并到主分支中

git request-pull master origin feature-x
Run Code Online (Sandbox Code Playgroud)

将向您展示会发生什么(没有做任何事情):

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
Run Code Online (Sandbox Code Playgroud)

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

  • 你可以通过在命令行选项中添加`master`和`origin`来做得更清楚一点,如果我在例如本地`branch1`上并想要做一个`request-pull`,那该怎么办呢?本地功能分支`branch2`?我还需要`origin`吗?当然,人们总是可以阅读文档. (3认同)

小智 19

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

假设你想从测试合并your_branchmaster(我假设你已经master签出):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch
Run Code Online (Sandbox Code Playgroud)

这应该够了吧.

如果你得到错误

error: patch failed: test.txt:1
error: test.txt: patch does not apply
Run Code Online (Sandbox Code Playgroud)

这意味着补丁不成功,合并会产生冲突.没有输出意味着补丁是干净的,你可以轻松合并分支


请注意,这实际上不会更改您的工作树(当然,除了创建补丁文件,但之后您可以安全地删除它).从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".
Run Code Online (Sandbox Code Playgroud)

对于那些比我更聪明/更有经验的人,请注意:如果我在这里错了,请告诉我这个方法确实表现出与常规合并不同的行为.看起来奇怪的是,在这个问题存在的8年多时间里,没有人会提出这个看似明显的解决方案.

  • 这种方法是[这个问题](/sf/ask/443500221/)接受的答案评论中有一些警告,例如“git 无法使用‘递归’合并策略”和“补丁文件为新文件提供错误”。否则,看起来很棒。 (2认同)
  • 不创建临时补丁文件的更短方法:`git diff master your_branch | git apply --check`。 (2认同)

小智 8

这可能很有趣:来自文档:

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

但你也可以采用天真(但很慢)的方式:

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)
Run Code Online (Sandbox Code Playgroud)

(注意:只有克隆到/ tmp才会起作用,你需要一个副本,以确保未提交的更改不会发生冲突).

  • 如果你需要的只是锤子...... :) +1 (2认同)

Jas*_*dly 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
Run Code Online (Sandbox Code Playgroud)

  • 这真的不一样。以非零状态退出,因为无法以快进方式解决合并 ** 并不意味着存在冲突**。这只是意味着历史已经发生分歧并且需要合并提交。 (3认同)
  • 如果可以通过快进完成合并,那么这将完成合并,这不是我在原来的问题中想要的。我认为已接受的答案有另一半可以修复它。 (2认同)

Ube*_*esh 8

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

不要将您的分支合并到远程“目标”分支,而是将该分支合并到您的分支中。

git checkout my-branch
git merge origin/target-branch
Run Code Online (Sandbox Code Playgroud)

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

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


nel*_*nzo 6

我使用git log来查看master分支的功能分支上发生的变化

git log does_this_branch..contain_this_branch_changes
Run Code Online (Sandbox Code Playgroud)

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

git log master..feature_branch
Run Code Online (Sandbox Code Playgroud)


小智 6

我只想查看冲突(目前在 GitHub 中还看不到它们diff3)。充分利用上面的答案,我想出了这个:

git merge --no-commit --no-ff @{upstream}
git grep -l '<<<<<<< HEAD' | xargs -I % sh -c "echo -e '\n\e[93m%\n---\e[0m' && cat %"
git merge --abort
Run Code Online (Sandbox Code Playgroud)

对我来说,这是为了检查我的 PR。你可以@{upstream}用任何分支代替。

我希望这对某人有帮助。