Cel*_*tas 1 git github merge-conflict-resolution
我承诺,但意识到信息中有错误.我跑了
git commit --amend -o -m "blah blah"
然后我删除了文件(故意)然后做了
git add .
git commit -m "blah blah"
git push origin master
Run Code Online (Sandbox Code Playgroud)
并得到了错误
![拒绝]主人 - >主人(非快进)
我试着解决它git pull origin master并得到了
CONFLICT (modify/delete): MyFile.java deleted in HEAD and modified in ad0c109
发生了什么,我该如何解决?我只想要有一个删除文件的历史记录.我打算用同一个名字创建一个新的.
更新:
我跑了git push -f origin master,它工作.现在git status给出
在分支主机上所有冲突都已修复,但您仍在合并.(使用"git commit"来结束合并)
我跑了git commit,得到了
E325:注意找到一个名为"C:/Users/Dev3/Documents/NetBeansProjects/OctRecProj/src/OctRecProj/.git/.COMMIT_EDITMSG.swp"的交换文件所拥有者:Dev3日期:Sun May 22 03:27:31 2016文件名:~Dev3/Documents/NetBeansProjects/OctRecProj/src/OctRecProj/.git/COMMIT_EDITMSG修改:YES用户名:Dev3主机名:Desktop-D进程ID:2844打开文件"C:/ Users/Dev3/Documents/NetBeansProjects/OctRecProj/src/OctRecProj/.git/COMMIT_EDITMSG"日期:星期四10月13日03:22:34 2016 NEWER比交换文件!
(1)另一个程序可能正在编辑同一个文件.如果是这种情况,请注意在进行更改时不要以同一文件的两个不同实例结束.退出,或继续谨慎.(2)此文件的编辑会话崩溃.如果是这种情况,请使用":recover"或"vim -r C:/ Users/Dev3/Documents/NetBe ansProjects/OctRecProj/src/OctRecProj/.git/COMMIT_EDITMSG"来恢复更改(请参阅":help recovery" ).如果你已经这样做了,删除交换文件"C:/ Users/Dev3/Documents/NetBe ansProjects/OctRecProj/src/OctRecProj/.git/.COMMIT_EDITMSG.swp" - 更多 -
让我们做几个注释,然后绘制一些提交图,因为这些git merge动作主要依赖于提交图和附加到三个"有趣"提交的树.
git commit --amend不修改提交(因为这是不可能的).相反,它会进行新的提交并将旧的提交推到一边,为新的提供空间,而不是通常"在最后添加新的".
git commit -o(或--only)省略当前索引(暂存区域),而是从上一次提交开始创建临时索引.在修改时这是一个合理的事情,尽管如果你没有上演任何东西,这没有任何效果.所以这个"修改"(真的,复制的)提交将与原始提交具有相同的树,即使你已经上演了一些东西.(这仅适用于注释3)
最后,后续git commit(在删除文件并暂存删除之后)将进行新的提交,删除文件,以及您已经上传的任何其他内容(如注释2中所述).
现在,我们不知道你在这里修改的提交是否是一个合并提交本身,但让我们假设它不是.(如果是的话,图片变得更复杂,但结果是一样的.)我们也不确定,但可以合理地假设,你正在修改的提交已被推送 - 因为这正是导致的这个问题.所以,我们可以像这样绘制图形.
首先,我们绘制"之前"的情况:在你修改任何东西之前.该图非常简单:
...--o--*--A <-- master, origin/master
Run Code Online (Sandbox Code Playgroud)
也就是说,你的分支master指向提交A(我们即将"修改"的origin/master那个),并且 - 你master在其他Git存储库中看到的副本,在机器上origin- 也指向提交A.提交*就是之前的提交A; 这个将在以后重要.还有其他早期的提交.
现在让我们在修改之后绘制图形,但在进行任何新提交之前:
A <-- origin/master
/
...--o--*
\
A' <-- master
Run Code Online (Sandbox Code Playgroud)
Commit A'是修改后的提交,消息略有不同.它与提交相同的树A - 相同的源代码 - 但是不同的消息,因此具有不同的SHA-1 ID.
让我们添加删除文件的提交,并D为Delete 调用它:
A <-- origin/master
/
...--o--*
\
A'-D <-- master
Run Code Online (Sandbox Code Playgroud)
您现在尝试git push origin master并收到错误.这个错误是因为,on origin,他们 master提交的要点A,或者甚至A是你没有提交的一些提交.1 让我们继续理论,这origin不是一个超级活跃的存储库,每秒获得10次新提交或者其他任何东西,并希望它只是A.:-)
他们的Git origin抱怨的是,如果他们让你这样做git push,他们将"失去"承诺A.你的Git要求他们的Git设置他们 master的指向你的提交D(当然,之后,移交你A'和你的D).如果他们这样做,他们将不再有一个指向commit的名称A:commit A将被遗忘.
当然,这正是您在修改时对自己的存储库所做的A.你告诉你的Git:"忘记了A,把它推到一边,这是唯一的名字origin/master,给我A'一份不同的信息."
好的,到目前为止一直很好,除了推送失败.所以,你跑了git pull origin master.
1虽然你现在可以看到你现在所拥有的东西,但却与他们在跑步时所拥有的东西相匹配,所以不可能准确地说出他们当时拥有的东西git pull.当然git pull,至少整整几秒钟你都知道了,谁知道那段时间有多少变化!说真的,有一个同步问题,因为无论你在Git中做什么,其他人现在可能正在其他Gits中做其他事情.这对你来说有多大问题取决于活跃origin程度.
git pull是不是相反git push事实上,没有完全相反的git push.最接近的是git fetch,它告诉你的Git调用他们的Git,就像推送一样,但不是向他们发送你的提交并要求他们移动他们的分支,你得到他们的提交,你让你的Git移动你的"远程" - 跟踪分支":你的origin/master.
git pull首先运行什么git fetch,然后运行git merge.
git fetch第一部分git pull origin master是Git运行git fetch origin master.
这fetch一步调用了他们的Git并带来了他们的新提交.我们假设没有:他们master仍然指向他们A,这也是你的A.所以你的Git更新了你的origin/master指向你的A(没有太多的更新:没有改变):
A <-- origin/master
/
...--o--*
\
A'-D <-- master
Run Code Online (Sandbox Code Playgroud)
(如果他们其实有一定的提交,让我们给他们打电话B和C-那么你的Git获得这些提交和更新了origin/master:
A--B--C <-- origin/master
/
...--o--*
\
A'-D <-- master
Run Code Online (Sandbox Code Playgroud)
但可能没有这样的提交.让我们在没有他们的情况下继续.)
git merge第二部分git pull origin master是运行git merge,有一些额外的参数太复杂,无法准确再现,但或多或少相当于origin/master.2 让我们假装它真的是git merge origin/master,因为这更容易使用.
什么git merge做的是先找到合并基础,这是第一个承诺是相同的电流之间的分支,那就是你master-和提交你告诉它该合并提交你(或者git pull,真的)告诉你的GIT中merge in是tip origin/master,即commit A.
所以现在我们回到我们绘制的图表并找到合并基础.这是承诺*.我们还找到了提示的提示origin/master,即提交A,以及我们当前分支的提示:commit D.
接下来,我们制作(或Git制作)两个git diff列表:
git diff <id-of-*> <id-of-A> # "what they changed"
git diff <id-of-*> <id-of-D> # "what we changed"
Run Code Online (Sandbox Code Playgroud)
据推测,在提交*和提交之间A,"他们"(无论他们是谁,也许是我们)改变了你删除的文件D.
同时,在提交*和提交之间D,"我们"删除了该文件.请注意,Git甚至不在这里查看提交A':它只是比较*和D.不要紧,我们之间的相同的方式更改的文件*和A',它唯一要紧的是,我们在整体变化删除了该文件.
这是合并冲突的根源. 在"他们做了什么"和"我们做了什么"之间,Git不知道是保留对文件的更改,还是保留文件的删除.
如果您希望进行合并 - 您可能没有 - 您可以通过运行git rm <file>然后git commit提交合并来解决此问题.结果将是一个新的合并提交:
A <-- origin/master
/ \
...--o--* \__
\ \
A'-D--M <-- master
Run Code Online (Sandbox Code Playgroud)
新合并的树将与提交的树匹配D,但现在您将在历史记录中同时拥有原始提交A 和修改后的副本(具有相同的树但具有不同的提交消息).
你可以将其推送到origin,因为现在如果你发送它们M并要求它们设置它们master指向M它们,它们就不会丢失提交A.
2差异主要显示在默认的合并提交消息中,该消息大致表示"将名为master的分支从远程命名源"合并而不是"合并我们自己的远程跟踪分支origin/master".此外,如果你有一个古老版本的Git,比1.8.4早,还有一些额外的技术陷阱,阻止origin/master在这里工作.希望你不会受到Git 1.7.x版的困扰.
首先,您可以中止正在进行的合并:
git merge --abort
Run Code Online (Sandbox Code Playgroud)
现在你回到原来的:
A <-- origin/master
/
...--o--*
\
A'-D <-- master
Run Code Online (Sandbox Code Playgroud)
在您的存储库中.
这里的一个大问题是,无论他们是谁,他们都会origin承诺A.您可以使用强制推动来让它们放弃它:
git push --force origin master
Run Code Online (Sandbox Code Playgroud)
这告诉他们的Git"继续前进并失去提交A,只是设置你master的D.缺点是,如果他们已经获得了一些提交B和/或C现在,你也将丢失这些提交.此外,如果其他人已经获得了提交副本A,其他用户必须做一些事情来从您的重置恢复origin到放弃A支持A'.
--force-with-lease实际上,你可以用它来告诉他们"我相信你的master要点可以提交A;如果有的话,请master指出你的意思D." (这要求你的Git和他们的Git都足够新,可以--force-with-lease选择.)
或者,您可以放弃修改提交消息的想法.只需屈服并移植你的提交,D以便它来之后A,而不是之后A'.A'完全放弃修改,给你这个图:
A <-- origin/master
/ \
...--o--* D' <-- master
\
A'-D [abandoned]
Run Code Online (Sandbox Code Playgroud)
您现在可以推送它,因为您D'的原始副本D只会添加到其现有提交中A.如果,在这样做之后,我们完全忘记了被遗弃的提交并且更好地绘制了这个,我们得到:
...--o--*--A--D <-- master, origin
Run Code Online (Sandbox Code Playgroud)
这是一个很好的直接历史,是你所希望的.
在git merge --abort用于转义正在进行的合并之后,您的三个选项是:
D进入D',或重复删除操作来创建D',重设自己的后master指向同一个地方origin/master.(如果origin足够私有,选项1是安全且容易的.[另外,在进行正在进行的合并时进行推送在很大程度上是无害的,因为推送仅推送完成的提交.])
| 归档时间: |
|
| 查看次数: |
1364 次 |
| 最近记录: |