我对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为B
和C
(我不知道哪个是哪个)。我错过了那一个,并在B
和C
之间为每次冲突选择(总共6次)。这就是我被卡住的地方。
首先输出文件(位于A
下方B
,C
和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
看起来修改后的文件是kdiff3保存的输出,因此已经添加到索引中,因此我可以提交。那是对的吗?我假设在这种情况下我只是承诺完成合并?
总的来说,我不确定这里发生了什么 - 为什么&#34; git status&#34;显示4个带有扩展名的未跟踪文件(即.LOCAL
,.REMOTE
,.orig
和SuperAdventureConsole/SuperAdventureConsole.csproj
),但在&#中显示.LOCAL
没有扩展名34;改性&#34;文件列表?
我了解.REMOTE
和.BASE
,但.orig
和Config.textEscaper = text -> text;
之间的区别是什么?其中一个应该是两个分支的父级,但是哪一个是它,另一个是什么?
此外,我是否可以从Git Bash或使用Git Extensions或其他Git GUI来检查合并是否已准备好以我期望的方式提交?
谢谢!
答案 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
脚本主要使用它来比较所选合并程序退出时原始文件中的内容。