我刚刚在git中合并了一个分支到我的master中,我得到了自动合并失败;修复冲突,然后提交结果。现在我运行git mergetool和vimdiff,打开下图。我不知道如何使用vimdiff。这里的每个面板是什么意思,我应该如何修复合并冲突?
这四个缓冲区提供了同一文件的不同视图。左上方的缓冲区(LOCAL)是文件在目标分支(合并到的分支)中的外观。右上角的缓冲区(REMOTE)是文件在源分支(从哪里合并)中的外观。中间的缓冲区(BASE)是这两个缓冲区的共同祖先(因此您可以比较左版本和右版本之间的差异)。
I may be mistaken on the following point. I think the source of the merge conflict is that both files have changed the same portion of the file since BASE; LOCAL has changed the quotes from double to single, and REMOTE has made the same change but also changed the background value from a color to a URL. (I think the merge is not smart enough to notice that all the changes to LOCAL are also present in REMOTE; it just knows that LOCAL has made changes since BASE in the same places that REMOTE has).
In any case, the bottom buffer contains the file you can actually edit—the one sitting in your working directory. You can make any changes you like; vim is showing you how it differs from each of the top views, which are the areas that the automatic merge couldn't not handle. Pull changes from LOCAL if you don't want the REMOTE changes. Pull changes from REMOTE if you prefer those to the LOCAL changes. Pull from BASE if you think both REMOTE and LOCAL are wrong. Do something completely different if you have a better idea! In the end, the changes you make here are the ones that will actually be committed.
@chepner的回答很好,我想补充一些关于“我应该如何修复合并冲突”这部分问题的细节。如果您研究一下在这种情况下如何实际使用vimdiff,它如下所示。
首先,解决“中止一切”选项-如果你不想使用“vimdiff”,并想要中止合并:按Esc,然后键入:qa!并按Enter键。(请参见如何退出Vim编辑器?)Git会问你合并是否完成,回复n。
如果您想使用vimdiff,这里有一些有用的快捷方式。这里假设你知道Vim的基础知识(导航和插入/正常模式):
navigate to the bottom buffer (merge result): Ctrl-W j navigate to next diff with j/k; or, better, use ] c and [ c to navigate to the next and previous diff respectively use z o while on a fold to open it, if you want to see more context for each diff, as per @chepner's answer, you can either get the code from a local, remote or base version, or edit it and redo as you see fit to get it from the local version, use :diffget LO from remote: :diffget RE from base: :diffget BA or, if you want to edit code yourself, get a version from local/remote/base first, and then go to the insert mode and edit the rest once done, save the merge result, and quit all windows :wqa if you want to abort merging the current file and not mark it as resolved, quit with :cquit instead: How do you cancel an external git diff? normally, git detects that the merge was made and creates the merge commit
如果没有复制粘贴或自定义快捷方式,似乎不可能同时添加本地和远程冲突块:https://vi.stackexchange.com/questions/10534/is-there-a-way-to-take-both-when-using-vim-as-merge-tool,这很遗憾,因为add add是如此常见的冲突类型。
为了防止vimdiff每次启动时都要求你按enter,在你的.vimrc中添加:
set shortmess=Ot
如上所述:https://vi.stackexchange.com/questions/771/how-can-i-suppress-the-press-enter-prompt-when-opening-files-in-diff-mode
您可以在互联网上搜索其他vimdiff快捷方式。我发现这个很有用:https://gist.github.com/hyamamoto/7783966
取代vimdiff的终极合并工具
这是一种半开玩笑的说法,但在尝试vimdiff之后,我最终成为了一名vimmer。
要解决合并冲突,我几乎总是需要看到:
远程 当地的 两个差别: diff BASE遥控器 diff BASE LOCAL
然后试着把它们放在一起。
vimdiff在屏幕上显示BASE, LOCAL和REMOTE:
+--------------------------------+
| LOCAL | BASE | REMOTE |
+--------------------------------+
| MERGED |
+--------------------------------+
我不知道怎样才能清楚地显示出我需要的这两个差值除了不断地看左右左右。
此外,LOCAL和REMOTE已经在git合并冲突标记中可见,因此我不会从再次显示它们的工具中获得太多信息。
因此,我反而创建了自己的小“difftool”,它实际上显示了我所缺少的差异:
~/bin/cirosantilli-mergetool
#!/usr/bin/env bash
BASE="$1"
LOCAL="$2"
REMOTE="$3"
diff --color -u "$BASE" "$LOCAL"
diff --color -u "$BASE" "$REMOTE"
exit 1
GitHub上游。
并安装:
git config --global mergetool.cirosantilli-mergetool.cmd 'cirosantilli-mergetool $BASE $LOCAL $REMOTE'
git config --global mergetool.cirosantilli-mergetool.trustExitCode true
# If you want this to become your default mergetool.
#git config --global merge.tool 'cirosantilli-mergetool'
现在,当你这样做时:
git mergetool -t cirosantilli-mergetool
它显示了我想在终端上的两个差分,例如沿着:
--- ./src/dev/arm/RealView_BASE_15560.py 2019-12-27 13:46:41.967021591 +0000
+++ ./src/dev/arm/RealView_LOCAL_15560.py 2019-12-27 13:46:41.979021479 +0000
@@ -994,7 +994,7 @@
def setupBootLoader(self, cur_sys, loc):
if not cur_sys.boot_loader:
- cur_sys.boot_loader = [ loc('boot_emm.arm64'), loc('boot_emm.arm') ]
+ cur_sys.boot_loader = [ loc('boot.arm64'), loc('boot.arm') ]
cur_sys.atags_addr = 0x8000000
cur_sys.load_offset = 0x80000000
@@ -1054,7 +1054,7 @@
]
def setupBootLoader(self, cur_sys, loc):
- cur_sys.boot_loader = [ loc('boot_emm_v2.arm64') ]
+ cur_sys.boot_loader = [ loc('boot_v2.arm64') ]
super(VExpress_GEM5_V2_Base,self).setupBootLoader(
cur_sys, loc)
--- ./src/dev/arm/RealView_BASE_15560.py 2019-12-27 13:46:41.967021591 +0000
+++ ./src/dev/arm/RealView_REMOTE_15560.py 2019-12-27 13:46:41.991021366 +0000
@@ -610,10 +610,10 @@
def attachIO(self, *args, **kwargs):
self._attach_io(self._off_chip_devices(), *args, **kwargs)
- def setupBootLoader(self, cur_sys, loc):
- cur_sys.boot_loader = loc('boot.arm')
- cur_sys.atags_addr = 0x100
- cur_sys.load_offset = 0
+ def setupBootLoader(self, cur_sys, boot_loader, atags_addr, load_offset):
+ cur_sys.boot_loader = boot_loader
+ cur_sys.atags_addr = atags_addr
+ cur_sys.load_offset = load_offset
所以你可以在这里看到两个差分被转储到终端:
RealView_BASE_15560.py vs RealView_LOCAL_15560.py RealView_BASE_15560.py vs RealView_REMOTE_15560.py
如果差异很大,我就用我的tmux超能力搜索。
待办事项:要达到涅槃的最后一件事将是一种方式,显示只有分歧的冲突帅哥。因为如果差异很大,但只有一个小块冲突,找到它是很烦人的。
是的,您确实丢失了vimdiff提供的一些快捷方式,但一般来说,解决冲突需要仔细地从两个版本中复制粘贴,我可以在正常的vim会话中使用git冲突标记完成这一点。
在vimdiff运行时观察和区分文件
在我坐下来,用cirosantilli-mergetool自动化我的完美设置之前,这是我所做的,以获得我需要的两个差分。
当git mergetool运行vimdiff时,如果在一个名为main.py的文件上有冲突,git会为每个版本生成文件,命名为:
main_BASE_1367.py
main_LOCAL_1367.py
main_REMOTE_1367.py
在与main.py相同的目录中,其中1367是git合并工具的PID,因此是一个“随机”整数,如上文所述:在git合并冲突中,生成的BACKUP, BASE, LOCAL和REMOTE文件是什么?
所以,为了看到我想要的差异,我首先找到生成的git状态的文件,然后打开新终端,在我关心的文件对之间执行vimdiff:
vim -d main_BASE_1367.py main_LOCAL_1367.py
vim -d main_BASE_1367.py main_REMOTE_1367.py
与git mergetool一起使用,这些信息可以帮助您快速了解正在发生的事情!
此外,即使mergetool正在运行,你也可以打开文件:
vim main.py
直接在那里编辑,如果你觉得用一个更大的编辑器窗口会更容易。
直接跳转到合并冲突
虽然]c跳转到vimdiff内部的下一个diff点,但并不总是存在合并冲突。
为了做到这一点,我在~/.vimrc中有:
# Git Merge conflict
nnoremap <leader>gm /\v^\<\<\<\<\<\<\< \|\=\=\=\=\=\=\=$\|\>\>\>\>\>\>\> /<cr>
直接找到冲突。
git imerge
也许最好的选择是放弃使用vimdiff,而依赖常规的vim + git镜像,这在文章中提到过:我如何知道哪些git提交会导致冲突?因为vimdiff的学习曲线很烦人,而且它不做我们最需要的函数。