ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我在 git-merge 上没有看到类似 --dry-run 的内容。

这可能会帮助您:stackoverflow.com/questions/5817579/…
再解释一下:我不想碰工作树,因为我不想让它签出。如果我想查看多个分支机构的此信息,那将需要很长时间。
哦 - 你的意思是你不想保留目标分支的本地副本?
既然使用 Git 进行分支很便宜,为什么不签出一个副本,然后就不需要进行试运行呢?之后你可以扔掉副本。
很高兴知道:自 06/01/20 以来,有一个用于拉动的空运行标志(但仍然不是用于合并)

C
Community

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

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

要检查分阶段的更改:

$ git diff --cached

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

$ git merge --abort

答案应该提到退出状态是 0 如果合并是可能的。
凉爽的!但是如何撤消此操作?它说“所有冲突都已解决,但您仍在合并”。调用 git checkout . 不会将文件恢复到合并前状态。
非易失性存储器。弄清楚了。你打电话给git merge --abort
谢谢一堆。它确实解决了我在开发合并功能方面遇到的一个非常极端的问题,该问题将方法主体(没有冲突)重写回旧版本,因为功能分支没有被重新定位(使用 Intellij 想法,最终2021.2 与 Windows 上的 git 版本 2.25.0)。 Intellij 的合并选项默认没有上述选项......有了它们,合并立即标记“静默”冲突。
T
Trevor Hickey

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

获取远程到您的存储库。例如: git fetch origin master 运行 git merge-base: git merge-base FETCH_HEAD master 运行 git merge-tree: git merge-tree mergebase master FETCH_HEAD (mergebase是上一步merge-base打印的十六进制id)

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


顺便说一句,步骤 2 和 3 可以合并为一个步骤,使用 Linux 控制台的反引号运算符,它就地评估其内容:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
添加到 .gitconfig 中的 [alias]:dry = "!f() { git merge-tree `git merge-base $2 $1` $2 $1; }; f" #检查 dev 到 master 的合并将如何进行:git dry开发大师
我最喜欢的 GIT 新系列:git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both" 简直太棒了! +100
在对此进行测试时,我发现 grepping for 'changed in both' flags 合并,其中两个分支都修改同一个文件,即使它们不会导致合并冲突。为了只识别实际的冲突,我发现有必要对以这样开头的冲突标记进行 grep:+<<<<<<< .our,所以我使用像 grep -q '^+<* \.our$' 这样的 grep 表达式
好的!这是我目前最喜欢的:git merge-tree $(git merge-base $1 $2) $1 $2 | sed -n '/+<<<<<<< .our/,/+>>>>>>> .their/p;/^changed in both/{n;N;N;s/^/#/mg;p}' | cdiff。它提取了“两行都发生了变化”以及冲突的部分。
I
Ian Robinson

我假设您只是想在实际尝试合并之前找出自己遇到了多少麻烦......并且在合并失败后重置到最后一次提交相对容易,所以如果那样我不会感到惊讶是预期的方法。

也就是说,如果您真的不想修改工作树中的现有文件 - 您可以创建一个补丁并针对目标分支对其进行测试。这还具有准确显示对哪些文件进行了哪些更改的好处 - 只需在文本编辑器中打开补丁文件即可。

git checkout -b mycrazybranch
[change some stuff...]
git add .
git commit -m "changed some stuff"
git format-patch master --stdout > crazy.patch
git checkout master
git apply crazy.patch --check
[all good! cleanup...]
rm crazy.patch

如您所见,这将创建一个补丁文件,然后您可以使用 --check 对其进行测试,看看是否有任何错误,然后删除补丁文件。


有效!如果您这样做,您甚至不需要临时文件:git format-patch master --stdout | git-apply --check -
@Penz 在我的 git v1.8.1.1 git-apply 中不起作用。它必须是 git apply
这对我来说并不准确 - git 在应用补丁时无法使用“递归”合并策略,因此它存在冲突,但它与“git 合并”配合得很好。
另一个问题,补丁文件为在新分支中创建的新文件提供错误。
m
manojlds

看到有冲突后可以做git merge --abort


是的,但如果你不想应用它,即使没有冲突,那也行不通。从字面上看,只是检查。
@OllieFord 将它与 --no-commit --no-ff 选项一起使用怎么样?
@SamuelRobert 换句话说:git merge other-branch --no-commit --no-ff; git merge --abort - 似乎工作得很好。
W
Will Beason

作为现有答案的总结,有两种方法可以检查是否存在合并冲突

git format-patch $(git merge-base branch1 branch2)..branch2 --stdout | git apply --3way --check -

请注意,当您运行上述命令时,您的当前分支应该是 branch1

另一种方式:

git merge --no-commit branch2
# check the return code here
git merge --abort

如果将 branch1 替换为 HEAD,则您的命令适用于任何分支。
实际上,您的第一个命令没有进行正确的 3 路合并,因此您会得到一堆误报。第二种方法效果更好。
@MarkLodato 我也更喜欢第二个,但您可以提供 --3way 给 git apply。
M
Michael

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

创建一个“pre-master”分支(当然来自 master)将所有你想要的东西合并到这个 pre-master 中。然后你可以在不接触 master 的情况下看到合并是如何发生的。将 pre-master 合并到 master 或将所有想要发布的分支合并到 master

无论如何,我会听从@orange80 的建议。


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

我为此做了一个别名,就像一个魅力,我这样做:

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

现在我只是打电话

git mergetest <branchname>

找出是否有任何冲突。


B
Brian Phillips

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

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

编辑:如以下评论中所述,如果您的工作目录或暂存区有更改,您可能希望在执行上述操作之前将它们隐藏起来(否则它们将在上面的 git reset 之后消失)


简单地检查合并是否快进 (FF) 就是检查 git branch --contains HEAD 的列表,或者更直接地,只需使用 git merge --ff-only
git reset --hard 是 git 为数不多的无回退信息删除命令之一,因此使用时应格外小心。因此,-1
@Tchalvak 还有 reflog。
--dry-run 不会“简单地检查合并是否会快进”。它将返回合并的确切输出:文件、冲突等。 ff 是否真的很有趣,是吗?
git stash; git reset --hard 怎么样? @布莱恩菲利普斯
t
timh

只需将您当前的分支与远程分支进行比较,这将告诉您在执行拉取/合并时会发生什么变化。

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

有趣的想法。我将如何查看该输出并确定合并是否有效?
这不会告诉您是否会发生任何冲突......但它会让您大致了解如果您进行拉/合并会发生什么。
这只会告诉你两个分支之间的区别,它不会告诉你合并的结果是什么。这是一个重要的区别,因为在某些情况下,合并会根据提交的时间自动从不同的分支中获取更改。因此,从本质上讲,进行 diff 可能会让您认为您的某些更改将被还原,而实际上,合并过程将自动采用新的更改而不是旧的更改。希望这是有道理的。
以@mirthlab 的评论为基础,如果有人之前使用“我们的”合并策略(或其他一些手动合并修复)执行了合并,则 diff 和 merge 之间会有显着差异;差异还将向您显示已被视为“合并”的差异。
A
Alexandre

不完全一样。但是您可以使用 --no-commit 选项,因此它不会在合并后自动提交结果。通过这种方式,您可以检查并在需要时撤消合并,而不会弄乱提交树。


A
ArnaudR

我使用 request-pull git 命令来执行此操作。它允许您查看合并时会发生的每一个更改,但无需对本地或远程存储库执行任何操作

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

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 一样。


您可以通过在命令行选项中添加 masterorigin 的功能来更清楚地说明这一点,如果我在本地 branch1 上并且想要在本地执行 request-pull 怎么办?功能分支 branch2?我还需要 origin 吗?当然,人们总是可以阅读文档。
遗憾的是,此命令仅在 Rev#2 是分支名称时才有效,它不适用于哈希:/
C
Christoph Böhmwalder

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

假设您要测试从 your_branchmaster 的合并(我假设您已签出 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 年多的时间里,没有人会提出这个看似显而易见的解决方案。


此方法是公认的答案 for this question,并且注释中有一些警告,例如“git 无法使用'递归'合并策略”和“补丁文件为新文件提供错误”。否则,看起来很棒。
不创建临时补丁文件的更短方法:git diff master your_branch | git apply --check
3
3 revs, 2 users 63%

Git 在合并时引入了一个 --ff-only 选项。

来自:http://git-scm.com/docs/git-merge --ff-only 拒绝合并并以非零状态退出,除非当前 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

如果可以通过快进来完成合并,这不是我在原始问题中想要的。我认为接受的答案有另一半可以解决。
但实际上,花哨的 git 提示消除了我对这类事情的需求。
真的不一样。以非零状态退出,因为合并无法解决,因为快进并不意味着存在冲突。这只是意味着历史已经分道扬镳,需要合并提交。
佚名

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

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

但你也可以用幼稚(但很慢)的方式来做:

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

(注意:仅克隆到 /tmp 是行不通的,您需要一份副本,以确保未提交的更改不会发生冲突)。


如果您只需要一把锤子... :) +1
可以使用 cp -r repository/.git /tmp/repository/.gitcd /tmp/repositorygit reset --hardgit add --allgit reset --hard(良好的衡量标准)、git status(检查它是否干净)来获得干净的副本。
n
nelsonenzo

我使用 git log 查看来自 master 分支的功能分支发生了什么变化

git log does_this_branch..contain_this_branch_changes

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

git log master..feature_branch

U
Ubeogesh

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

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

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

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

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


J
Jim Ivey

我想查看just 冲突(在 GitHub 中无法使用 diff3 看到它们)。大量利用 this answer above,我想出了这个:

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

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

我希望这对某人有帮助。


E
Erik Kaplun

如果你想从 B 快进到 A,那么你必须确保 git log B..A 什么都没有显示,即 A 没有 B 没有的任何东西。但是即使 B..A 有一些东西,你仍然可以在没有冲突的情况下合并,所以上面显示了两件事:会有一个快进,因此你不会发生冲突。


v
vanboom

制作工作副本的临时副本,然后合并到该副本中,并区分两者。


M
Mentor

我知道这在理论上是题外话,但对于从谷歌搜索到这里的人来说,这实际上是非常切题的。

如有疑问,您始终可以使用 Github 界面创建拉取请求并检查它是否表明可以进行干净的合并。


如果你使用 GitHub、GitLab 或类似的东西,这可能很有用。但情况并非总是如此。了解命令行的方式才是真正的力量。
我同意,只是添加了如果不太喜欢 cli 的人,他们今天过得很糟糕,并从谷歌登陆这里。