这个Git合并是否已经完成 - 或者如何用kdiff3完成它?

时间:2017-08-14 21:47:50

标签: c# git git-merge

背景

我对Git很新,并解决了我的第一次合并冲突。我在Scott Lilly C# SuperAdventure tutorial上使用Visual Studio在C#中工作。在构建教程的同时,我也使用Github来学习SCM和Git。作为这个过程的一部分,我学会了一个干净的大师直接跟随教程没有偏差,为每个章节创建一个分支,并在最后将它合并回主人,然后在不同的分支上保持任何实验 - 这样我的实验在创建新功能或重构现有代码时从不与教程冲突。

到目前为止,这么好。我的一个实验是添加一些单元测试。我开始了一个单独的unittesting分支,并决定将更改从master转到此分支以使其保持最新状态。在第一次合并时,由于安装了不同的软件包,我在项目的Visual Studio项目文件中出现了冲突,我正在添加单元测试。这不是什么大不了的事,但机制让我感到沮丧。添加中有5个冲突,可以直接合并,还有一个真正的冲突。我已经完成了大部分工作,但只需要一些最后的帮助。

到目前为止一步一步

我在Windows 10上使用a public repo on Github和Visual Studio 2017社区,使用VS Github扩展和本地Git仓库 - 但让我们面对它,Visual Studio插件命令是非常正常的工作流程项目。所以 - 我已经根据命令行的需要开始使用Git bash,而对于Git GUI开始使用Git Extensions,这是非常好的。

我最近完成了本教程的第23章,并将Chap_23分支合并到master。然后我尝试将master合并到unittesting,但在SuperAdventureConsole / SuperAdventureConsole.csproj文件中出现了冲突。此时的git状态显示:

$ git status
On branch unittesting
Your branch is ahead of 'origin/unittesting' by 1 commit.
  (use "git push" to publish your local commits)
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:

        modified:   SuperAdventure.sln
        modified:   SuperAdventureConsole/App.config
        modified:   SuperAdventureConsole/Properties/AssemblyInfo.cs

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   SuperAdventureConsole/SuperAdventureConsole.csproj

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        SuperAdventureConsole/SuperAdventureConsole.csproj.BASE
        SuperAdventureConsole/SuperAdventureConsole.csproj.LOCAL
        SuperAdventureConsole/SuperAdventureConsole.csproj.REMOTE
        SuperAdventureConsole/SuperAdventureConsole.csproj.orig

此时我基于Q: How to resolve merge conflicts in Git?运行git mergetool,它运行kdiff3作为合并工具(在我的设置上,无论如何),原始文件为A文件,并且LOCAL和REMOTE为BC(我不知道哪个是哪个)。我错过了那一个,并在BC之间为每次冲突选择(总共6次)。这就是我被卡住的地方。

首先输出文件(位于A下方BC和kdiff3中的$ git mergetool No files need merging 下方)没有采取,但是在第3次尝试时,我保存了退出kdiff3,并且不再发生合并冲突:

$ git status
On branch unittesting
Your branch is ahead of 'origin/unittesting' by 1 commit.
  (use "git push" to publish your local commits)
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

        modified:   SuperAdventure.sln
        modified:   SuperAdventureConsole/App.config
        modified:   SuperAdventureConsole/Properties/AssemblyInfo.cs
        modified:   SuperAdventureConsole/SuperAdventureConsole.csproj

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        SuperAdventureConsole/SuperAdventureConsole.csproj.BASE
        SuperAdventureConsole/SuperAdventureConsole.csproj.LOCAL
        SuperAdventureConsole/SuperAdventureConsole.csproj.REMOTE
        SuperAdventureConsole/SuperAdventureConsole.csproj.orig

但是,我仍然有未经跟踪的文件,每个&#34; git status&#34;:

.BASE

问题(S)

看起来修改后的文件是kdiff3保存的输出,因此已经添加到索引中,因此我可以提交。那是对的吗?我假设在这种情况下我只是承诺完成合并?

总的来说,我不确定这里发生了什么 - 为什么&#34; git status&#34;显示4个带有扩展名的未跟踪文件(即.LOCAL.REMOTE.origSuperAdventureConsole/SuperAdventureConsole.csproj),但在&#中显示.LOCAL没有扩展名34;改性&#34;文件列表?

我了解.REMOTE.BASE,但.origConfig.textEscaper = text -> text; 之间的区别是什么?其中一个应该是两个分支的父级,但是哪一个是它,另一个是什么?

此外,我是否可以从Git Bash或使用Git Extensions或其他Git GUI来检查合并是否已准备好以我期望的方式提交?

谢谢!

1 个答案:

答案 0 :(得分:2)

  

看起来修改后的文件是kdiff3保存的输出,因此已经添加到索引中,因此我可以提交。那是对的吗?我假设在这种情况下我只是承诺完成合并?

这看起来就像是这样。使用git diff --cached(或git diff --staged,如果您愿意:两者都做同样的事情)来比较现在的索引中的内容,即 new <中的内容< / em>提交到当前提交中的内容。另见第二个问题的答案。

git status执行相同的git diff --cached,但使用--name-status,这样您才能看到添加,删除或修改的任何文件,而不是实际更改的内容。)

  

总的来说,我不确定这里发生了什么 - 为什么&#34; git status&#34;显示4个带有扩展名的未跟踪文件(即.BASE.LOCAL.REMOTE.orig)...

这有点神秘:它表明你仍然有git mergetool在跑。

在{em>失败合并后,git mergetool做什么是通过索引中留下的混乱来解决问题。请记住,索引,AKA 临时区域缓存三个名称 - 通常只是您构建下一个提交的地方。它有一个将进入新提交的每个文件的副本。但是,在合并失败期间,它可以包含每个失败合并文件的三个副本,而不只是一个。

(似乎只有一个文件的自动合并实际上失败了,即SuperAdventureConsole/SuperAdventureConsole.csproj。)

索引中的三个副本是:

  • 文件的合并基础版本。
  • 该文件的当前(HEAD--ours或-aha! - 本地)版本。
  • 该文件的另一个(--theirs或非常差的名称,远程)版本。

索引中的文件采用特殊的Git形式,因此git mergetool所做的就是将每个文件提取到工作树中的普通文件中。它还会将SuperAdventureConsole/SuperAdventureConsole.csproj中遗留的失败合并结果文件复制到.orig

然后,git mergetool运行您选择的文件合并程序。您可以在此程序中操作该文件。完成后,保存文件并退出。 mergetool脚本将.orig文件与最终版本进行比较,以查看您是否实际修复了任何内容,和/或查看程序中的退出代码。

如果你看起来对失败的合并做了些什么,那么git mergetool脚本应该删除至少三个,通常是这四个文件。事实并非这表明git mergetool仍在运行。您可以检查并确保它确实不是。也许有什么事情可以扼杀它,而且从来没有机会清理它。

  

我了解.LOCAL.REMOTE,但.BASE.orig之间的区别是什么?其中一个应该是两个分支的父级,但是哪一个是它,另一个是什么?

.LOCAL文件只是索引中的--ours版本(git show :2:<path>,在冲突期间)。 .REMOTE文件是--theirs版本(git show :3:<path>)。 .BASE文件是合并基础版本(普通父级,如您所说; git show :1:<path>)。 .orig是备份文件级合并的备份。 mergetool脚本主要使用它来比较所选合并程序退出时原始文件中的内容。