我正在合并一个可能有很多冲突的远程分支。我怎么知道它是否会发生冲突?
我在 git-merge
上没有看到类似 --dry-run
的内容。
如前所述,传入 --no-commit
标志,但为了避免快进提交,还要传入 --no-ff
,如下所示:
$ git merge --no-commit --no-ff $BRANCH
要检查分阶段的更改:
$ git diff --cached
即使是快进合并,您也可以撤消合并:
$ git merge --abort
我只需要实现一个自动发现存储库与其远程之间冲突的方法。该解决方案在内存中进行合并,因此它不会触及索引,也不会触及工作树。我认为这是解决此问题的最安全的方法。以下是它的工作原理:
获取远程到您的存储库。例如: 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。或者您可以将输出打印到文件并检查。如果您找到以“两者都已更改”开头的行,那么很可能会发生冲突。
git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"
简直太棒了! +100
+<<<<<<< .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
。它提取了“两行都发生了变化”以及冲突的部分。
我假设您只是想在实际尝试合并之前找出自己遇到了多少麻烦......并且在合并失败后重置到最后一次提交相对容易,所以如果那样我不会感到惊讶是预期的方法。
也就是说,如果您真的不想修改工作树中的现有文件 - 您可以创建一个补丁并针对目标分支对其进行测试。这还具有准确显示对哪些文件进行了哪些更改的好处 - 只需在文本编辑器中打开补丁文件即可。
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 -
git-apply
中不起作用。它必须是 git apply
。
看到有冲突后可以做git merge --abort
。
git merge other-branch --no-commit --no-ff; git merge --abort
- 似乎工作得很好。
作为现有答案的总结,有两种方法可以检查是否存在合并冲突
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
,则您的命令适用于任何分支。
--3way
给 git apply。
我对此的简单暴力解决方案是:
创建一个“pre-master”分支(当然来自 master)将所有你想要的东西合并到这个 pre-master 中。然后你可以在不接触 master 的情况下看到合并是如何发生的。将 pre-master 合并到 master 或将所有想要发布的分支合并到 master
无论如何,我会听从@orange80 的建议。
git merge --abort
,如果存在合并,您始终可以执行 git reset --hard HEAD~1
,或者执行 git reset --hard origin/master
。创建另一个分支会给你一种安全感,但如果你了解 git 的工作原理,你就会明白这是错位的恐惧。当担心不更改工作副本时,这没有提供任何解决方案。
git merge --no-commit
如果可以快进,则不会中止合并。 git merge --abort
如果合并则不起作用。如果你想把它写成一个脚本,那就很尴尬了,因为 git merge
没有给出足够好的错误代码来解释不同类型的冲突。使用新分支可防止损坏的脚本使您的存储库处于需要手动干预的状态。当然你不能失去任何东西。但是以其他方式构建更容易。
我为此做了一个别名,就像一个魅力,我这样做:
git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '
现在我只是打电话
git mergetest <branchname>
找出是否有任何冲突。
撤消与 git 的合并非常容易,您甚至不必担心空运行:
$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world
编辑:如以下评论中所述,如果您的工作目录或暂存区有更改,您可能希望在执行上述操作之前将它们隐藏起来(否则它们将在上面的 git reset
之后消失)
git branch --contains HEAD
的列表,或者更直接地,只需使用 git merge --ff-only
--dry-run
不会“简单地检查合并是否会快进”。它将返回合并的确切输出:文件、冲突等。 ff 是否真的很有趣,是吗?
git stash; git reset --hard
怎么样? @布莱恩菲利普斯
只需将您当前的分支与远程分支进行比较,这将告诉您在执行拉取/合并时会发生什么变化。
#see diff between current master and remote branch
git diff master origin/master
不完全一样。但是您可以使用 --no-commit 选项,因此它不会在合并后自动提交结果。通过这种方式,您可以检查并在需要时撤消合并,而不会弄乱提交树。
我使用 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 一样。
master
和 origin
的功能来更清楚地说明这一点,如果我在本地 branch1
上并且想要在本地执行 request-pull
怎么办?功能分支 branch2
?我还需要 origin
吗?当然,人们总是可以阅读文档。
我很惊讶还没有人建议使用补丁。
假设您要测试从 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 diff master your_branch | git apply --check
。
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 merge --abort 恢复。
但你也可以用幼稚(但很慢)的方式来做:
rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)
(注意:仅克隆到 /tmp 是行不通的,您需要一份副本,以确保未提交的更改不会发生冲突)。
cp -r repository/.git /tmp/repository/.git
、cd /tmp/repository
、git reset --hard
、git add --all
、git reset --hard
(良好的衡量标准)、git status
(检查它是否干净)来获得干净的副本。
我使用 git log 查看来自 master 分支的功能分支发生了什么变化
git log does_this_branch..contain_this_branch_changes
例如 - 查看已合并/未合并到 master 的功能分支中的提交:
git log master..feature_branch
我的解决方案是向后合并。
不要将您的分支合并到远程“目标”分支中,而是将该分支合并到您的分支中。
git checkout my-branch
git merge origin/target-branch
您将查看是否存在任何冲突,并可以计划如何解决它们。
之后,您可以通过 git merge --abort
中止合并,或者(如果没有任何冲突并且发生了合并)通过 git reset --hard HEAD~1
回滚到之前的提交
我想查看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}
。
我希望这对某人有帮助。
如果你想从 B 快进到 A,那么你必须确保 git log B..A 什么都没有显示,即 A 没有 B 没有的任何东西。但是即使 B..A 有一些东西,你仍然可以在没有冲突的情况下合并,所以上面显示了两件事:会有一个快进,因此你不会发生冲突。
制作工作副本的临时副本,然后合并到该副本中,并区分两者。
我知道这在理论上是题外话,但对于从谷歌搜索到这里的人来说,这实际上是非常切题的。
如有疑问,您始终可以使用 Github 界面创建拉取请求并检查它是否表明可以进行干净的合并。
不定期副业成功案例分享
0
如果合并是可能的。git checkout .
不会将文件恢复到合并前状态。git merge --abort