有没有一种很好的方法来解释如何解决Git中的合并冲突?
有没有一种很好的方法来解释如何解决Git中的合并冲突?
尝试: git mergetool
它会打开一个GUI,引导您完成每个冲突,然后您可以选择合并方式。有时它需要稍后进行一些手工编辑,但通常它本身就足够了。这肯定比手工做整件事要好得多。
根据@JoshGlover评论:
除非您安装GUI,否则该命令不一定会打开GUI。运行 git mergetool
对我来说导致了 vimdiff
正在使用。您可以安装以下工具之一来代替使用它: meld
, opendiff
, kdiff3
, tkdiff
, xxdiff
, tortoisemerge
, gvimdiff
, diffuse
, ecmerge
, p4merge
, araxis
, vimdiff
, emerge
。
以下是要使用的示例程序 vimdiff
用于解决合并冲突。基于 这个链接
步骤1:在终端中运行以下命令
git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false
这会将vimdiff设置为默认合并工具。
第2步:在终端中运行以下命令
git mergetool
第3步:您将看到以下格式的vimdiff显示
+----------------------+
| | | |
|LOCAL |BASE |REMOTE |
| | | |
+----------------------+
| MERGED |
| |
+----------------------+
这4个观点是
LOCAL - 这是当前分支的文件
BASE - 共同的祖先,文件在两个变化之前看起来如何
REMOTE - 您正在合并到您的分支机构的文件
合并 - 合并结果,这是在回购中保存的内容
您可以使用这些视图导航 ctrl+w
。您可以直接使用MERGED视图 ctrl+w
其次是 j
。
有关更多信息vimdiff navigation 这里 和 这里
步骤4。您可以通过以下方式编辑MERGED视图
如果您想从REMOTE获得更改
:diffg RE
如果您想从BASE获得更改
:diffg BA
如果您想从LOCAL获得更改
:diffg LO
第5步。保存,退出,提交和清理
:wqa
保存并退出vi
git commit -m "message"
git clean
删除diff工具创建的额外文件(例如* .orig)。
这是一个可能的用例,从顶部:
你要做一些改变,但是哎呀,你不是最新的:
git fetch origin
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.
所以你得到最新的并再试一次,但是有冲突:
git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.
所以你决定看一下这些变化:
git mergetool
哦,我,我的,上游改变了一些事情,但只是为了使用我的改变......不......他们的改变......
git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"
然后我们尝试最后一次
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Already up-to-date.
当当!
我发现合并工具很少帮助我理解冲突或解决方案。我通常更成功地在文本编辑器中查看冲突标记并使用git log作为补充。
以下是一些提示:
我发现的最好的事情是使用“diff3”合并冲突风格:
git config merge.conflictstyle diff3
这会产生如下冲突标记:
<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a
feature/topic branch.
>>>>>>>
中间部分是共同祖先的样子。这很有用,因为您可以将它与顶部和底部版本进行比较,以更好地了解每个分支上的更改内容,从而更好地了解每个更改的目的。
如果冲突只有几行,这通常会使冲突非常明显。 (知道如何解决冲突是非常不同的;你需要知道其他人正在做什么。如果你感到困惑,最好是把那个人叫到你的房间,这样他们就能看到你在看什么在。)
如果冲突时间较长,那么我会将这三个部分中的每一部分剪切并粘贴到三个单独的文件中,例如“我的”,“普通”和“他们的”。
然后我可以运行以下命令来查看导致冲突的两个差异:
diff common mine
diff common theirs
这与使用合并工具不同,因为合并工具也将包括所有非冲突的差异。我觉得这会分散注意力。
有人已经提到了这一点,但理解每个差异背后的意图通常对于理解冲突的来源和如何处理它非常有帮助。
git log --merge -p <name of file>
这显示了在共同祖先和要合并的两个头之间触及该文件的所有提交。 (因此它不包括在合并之前已存在于两个分支中的提交。)这有助于您忽略明显不是当前冲突因素的差异。
使用自动化工具验证您的更改。
如果您有自动化测试,请运行它们。如果你有 皮棉,运行。如果它是一个可构建的项目,那么在你提交之前构建它等等。在所有情况下,你需要做一些测试,以确保你的更改没有破坏任何东西。 (哎呀,即使没有冲突的合并也会破坏工作代码。)
未雨绸缪;与同事沟通。
提前规划并了解其他人正在进行的工作可以帮助防止合并冲突和/或帮助他们提前解决 - 而细节仍然是新鲜的。
例如,如果您知道您和另一个人都在进行不同的重构,这两个重构都会影响同一组文件,那么您应该提前相互交谈,并更好地了解每个人的变化类型。制造。如果您按顺序而不是并行地执行计划的更改,则可能会节省大量时间和精力。
对于跨越大量代码的主要重构,您应该强烈考虑连续工作:当一个人执行完整的重构时,每个人都停止在代码的该区域工作。
如果你不能连续工作(由于时间压力,也许),那么沟通预期的合并冲突至少可以帮助你更快地解决问题,同时细节仍然是新鲜的。例如,如果同事在一周的时间内进行了一系列破坏性的提交,您可以选择在该周期间每天一次或两次合并/重组该同事分支。这样,如果你确实发现了合并/ rebase冲突,你可以比等待几周将所有内容合并成一个大块的更快地解决它们。
如果您不确定合并,请不要强迫它。
合并可能会让人感到压力,特别是当存在大量冲突文件且冲突标记覆盖数百行时。通常在评估软件项目时,我们没有足够的时间来处理开销项目,例如处理粗糙的合并,因此花费几个小时来解决每个冲突感觉真的很麻烦。
从长远来看,提前规划并了解其他人正在开展的工作是预测合并冲突并准备好在更短的时间内正确解决冲突的最佳工具。
确定哪些文件存在冲突(Git应该告诉您)。
打开每个文件并检查差异; Git划定了他们。希望很明显每个块的哪个版本要保留。您可能需要与提交代码的开发人员讨论它。
一旦解决了文件中的冲突 git add the_file
。
一旦你解决了 所有 冲突,做 git rebase --continue
或任何命令
当你完成时Git说要做。
查看Stack Overflow问题中的答案 在Git中中止合并特别是 Charles Bailey的回答 其中显示了如何查看具有问题的文件的不同版本,例如,
# Common base version of the file.
git show :1:some_file.cpp
# 'Ours' version of the file.
git show :2:some_file.cpp
# 'Theirs' version of the file.
git show :3:some_file.cpp
当同时对文件进行更改时,会发生合并冲突。这是如何解决它。
git
CLI以下是进入冲突状态时要执行的操作的简单步骤:
git status
(下 Unmerged paths
部分)。通过以下方法之一单独解决每个文件的冲突:
使用GUI解决冲突: git mergetool
(最简单的方法)。
要接受远程/其他版本,请使用: git checkout --theirs path/file
。这将拒绝您对该文件所做的任何本地更改。
要接受本地/我们的版本,请使用: git checkout --ours path/file
但是你要小心,因为远程改变冲突是出于某种原因。
手动编辑冲突的文件并查找之间的代码块 <<<<<
/>>>>>
然后从上方或下方选择版本 =====
。看到: 如何呈现冲突。
路径和文件名冲突可以通过解决 git add
/git rm
。
最后,使用以下命令查看准备提交的文件: git status
。
如果你还有任何文件 Unmerged paths
,你确实手动解决了冲突,然后让Git知道你解决了它: git add path/file
。
如果成功解决了所有冲突,请通过以下方式提交更改: git commit -a
像往常一样推到遥控器。
也可以看看: 从命令行解决合并冲突 在GitHub
我成功使用了 DiffMerge 它可以在Windows,macOS和Linux / Unix上直观地比较和合并文件。
它以图形方式显示3个文件之间的变化,它允许自动合并(在安全的情况下),并完全控制编辑生成的文件。
图片来源: DiffMerge (Linux截图)
只需下载并在repo中运行:
git mergetool -t diffmerge .
在macOS上,您可以通过以下方式安装
brew install caskroom/cask/brew-cask
brew cask install diffmerge
并且可能(如果未提供)您需要在PATH中放置以下额外的简单包装(例如, /usr/bin
):
#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"
然后您可以使用以下键盘快捷键:
或者你可以使用 了opendiff (Xcode Tools的一部分),它允许您将两个文件或目录合并在一起以创建第三个文件或目录。
如果您经常进行小型提交,那么首先查看提交注释 git log --merge
。然后 git diff
会告诉你冲突。
对于涉及多行的冲突,可以更容易地看到外部GUI工具中发生了什么。我喜欢opendiff - Git也支持vimdiff,gvimdiff,kdiff3,tkdiff,meld,xxdiff,emerge开箱即用,你可以安装其他人: git config merge.tool "your.tool"
将设置您选择的工具然后 git mergetool
合并失败后会在上下文中显示差异。
每次编辑文件以解决冲突时, git add filename
将更新索引,你的差异将不再显示它。当处理完所有冲突并且他们的文件已经存在时 git add
-ed, git commit
将完成您的合并。
看到 如何提出冲突 或者,在Git中, git merge
用于了解合并冲突标记的文档。
而且, 如何解决冲突 部分解释了如何解决冲突:
看到冲突后,你可以做两件事:
决定不合并。您需要的唯一清理是将索引文件重置为
HEAD
提交反向2.并清理由2.和3进行的工作树更改。git merge --abort
可以用于此。解决冲突。 Git将标记工作树中的冲突。将文件编辑为形状和
git add
他们到索引。使用git commit
达成协议。您可以使用许多工具解决冲突:
使用mergetool。
git mergetool
启动图形合并工具,它将帮助您完成合并。看看差异。
git diff
将显示三向差异,突出显示两者的变化HEAD
和MERGE_HEAD
版本。查看每个分支的差异。
git log --merge -p <path>
将首先显示差异HEAD
版本,然后MERGE_HEAD
版。看看原件。
git show :1:filename
显示共同的祖先,git show :2:filename
显示了HEAD
版本,和git show :3:filename
显示了MERGE_HEAD
版。
对于 Emacs的 想要半手动解决合并冲突的用户:
git diff --name-status --diff-filter=U
显示需要解决冲突的所有文件。
逐个打开每个文件,或者一次全部打开:
emacs $(git diff --name-only --diff-filter=U)
访问需要在Emacs中编辑的缓冲区时,请键入
ALT+x vc-resolve-conflicts
这将打开三个缓冲区(我的,他们的和输出缓冲区)。按'n'(下一个区域),'p'(预视区域)进行导航。按'a'和'b'分别将我或他们的区域复制到输出缓冲区。和/或直接编辑输出缓冲区。
完成后:按'q'。 Emacs会询问您是否要保存此缓冲区:是的。 完成一个缓冲区后,通过从teriminal运行解决它:
git add FILENAME
完成所有缓冲区类型后
git commit
完成合并。