我提交但意识到信息中有错误。我跑了
git commit --amend -o -m "blah blah"
然后我删除了文件(故意),然后
git add .
git commit -m "blah blah"
git push origin master
并收到错误
! [拒绝]主人 - >主人(非快进)
我尝试用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日期:2016年5月22日星期日03:27:31 文件名:~Dev3 / Documents / NetBeansProjects / OctRecProj / src / OctRecProj / .git / COMMIT_EDITMSG 修改:是的 用户名:Dev3主机名:Desktop-D 进程ID:2844打开文件" C:/ Users / Dev3 / Documents / NetBeansProjects / OctRecProj / SRC / OctRecProj / git的/ COMMIT_EDITMSG" 日期:2016年10月13日星期四03:22:34 比交换文件更新!
(1)另一个程序可能正在编辑同一个文件。如果这是 案件, 注意不要以两个不同的实例结束 进行更改时提交文件。退出,或继续谨慎。 (2)此文件的编辑会话崩溃。 如果是这种情况,请使用":recover"或" vim -r C:/ Users / Dev3 / Documents / NetBe ansProjects / OctRecProj / SRC / OctRecProj / git的/ COMMIT_EDITMSG" 恢复更改(请参阅":帮助恢复")。 如果您已经这样做,请删除交换文件" C:/ Users / Dev3 / Documents / NetBe ansProjects / OctRecProj / SRC / OctRecProj / git的/ .COMMIT_EDITMSG.swp" - 更多 -
答案 0 :(得分:5)
让我们做一些笔记,然后绘制一些提交图,因为git merge
的操作主要依赖于提交图和附加到的树这三个有趣的"提交。
git commit --amend
不会修改提交(因为这是不可能的)。相反,它做了一个新的提交并将旧的提交推到一边为新的提供空间,而不是做通常的"最后添加新的"。
git commit -o
(或--only
)省略当前索引(暂存区域),而是从上一次提交开始创建临时索引。在修改时这是一个合理的事情,尽管如果你没有上演任何东西,这没有任何效果。所以这"修改" (真的,复制)提交将具有与原始提交相同的树,即使您已经上演了某些内容。 (这仅适用于注释3。)
最后,后续的git commit
(在删除文件并暂存删除后)将进行新的提交,删除文件,以及已经上传的任何 else (如注2)所述。
现在,我们不知道您在此处修改的提交是否是合并提交本身,但我们只是假设它不是。 (如果是,图片会变得更复杂,但结果是相同的。)我们也不确定,但可以合理地假设,你提交的内容是修正已经被推 - 因为这正是导致这个问题的原因。所以,我们可以像这样绘制图形。
首先,我们在"之前绘制"情况:在你修改任何东西之前。该图非常简单:
...--o--*--A <-- master, origin/master
也就是说,您的分支master
指向提交A
(我们即将提交的#34;修改&#34;)和origin/master
- 您的副本如在另一个Git存储库中看到的master
,在机器上origin
- 也指向提交A
。提交*
是A
之前的提交;这个将在以后重要。还有其他早期的提交。
现在让我们在修改之后绘制图形,但在进行任何新提交之前:
A <-- origin/master
/
...--o--*
\
A' <-- master
提交A'
是修改后的提交,消息略有不同。它与提交A
具有相同的树 - 相同的源代码 - 但是不同的消息,因此具有不同的SHA-1 ID。
让我们添加删除文件的提交,并为D
elete调用此D
:
A <-- origin/master
/
...--o--*
\
A'-D <-- master
您现在尝试git push origin master
并收到错误消息。该错误是因为,在origin
上,他们的 master
指向提交A
,或者甚至是A
之后的某些提交没有。 1 让我们继续理论origin
不是一个超级活跃的存储库,每秒获得10次新提交或者其他任何东西,并且希望它和#39; s只是A
。 : - )
他们的Git在origin
上抱怨的是,如果他们让你这样做git push
,他们将会失去&#34;提交A
。你的Git要求他们的Git设置他们的 master
以指向你的提交D
(当然,之后,移交你的A'
和你的{{1 }})。如果他们这样做,他们将不再有一个指向提交D
的名称:将忘记提交A
。
当然,这正是您在修改A
时对自己的存储库所做的操作。你告诉你的Git:&#34;忘了A
,把它推到一边,其中唯一的名字是A
,并给我一个origin/master
副本,上面写着不同的消息&#34;
好的,到目前为止一切都很好,除了推送失败。所以你跑了A'
。
1 虽然你可以现在看到你现在拥有的东西,但它们不能准确地说出它们的含义当你跑git pull origin master
时他们有什么权利。当然,你的git pull
至少在几秒钟前完成了,谁知道那段时间发生了多大变化!说真的,有一个同步问题,因为无论你在Git中做什么,其他人现在可能正在其他Gits做其他事情。这对您来说有多大问题取决于git pull
的活跃程度。
origin
不与git pull
事实上,git push
并没有完全相反的情况。最接近的是git push
,它告诉你的Git调用他们的Git,就像推送一样,而不是发送你的提交并询问他们要移动他们的分支机构,您将获得他们的提交,并让您的Git移动您的&#34;远程跟踪分支机构&#34;:您的git fetch
。
origin/master
首先运行的是git pull
,然后运行git fetch
。
git merge
git fetch
的第一部分是Git运行git pull origin master
。
这个git fetch origin master
步骤调用了他们的Git并带来了他们的新提交。我们假设没有:他们的fetch
仍然指向他们的master
,这也是您的A
。因此,您的Git更新了您的A
以继续指向您的origin/master
(没有太多更新:没有任何更改):
A
(如果他们确实有一些提交 - 让他们称呼他们 A <-- origin/master
/
...--o--*
\
A'-D <-- master
和B
- 那么您的Git会获得这些提交并更新您的C
:
origin/master
但可能没有这样的提交。让它们在没有它们的情况下继续进行。)
A--B--C <-- origin/master
/
...--o--*
\
A'-D <-- master
git merge
的第二部分是运行git pull origin master
,其中一些额外的参数太复杂,无法准确再现,但或多或少等于git merge
。 2 < / sup>让我们假装它真的是origin/master
,因为它更容易使用。
git merge origin/master
做的是首先找到合并基础,这是您当前分支之间相同的第一个提交 - <#>你的git merge
- 以及你告诉它要合并的提交。你(或master
,真的)告诉你Git合并的提交是git pull
的提示,即,提交origin/master
。
现在我们回到我们正在绘制并找到合并基础的图表。那个提交A
。我们还找到*
的提示,即提交origin/master
,以及我们当前分支的提示:commit A
。
接下来,我们制作(或Git制作)两个D
列表:
git diff
据推测,在提交git diff <id-of-*> <id-of-A> # "what they changed"
git diff <id-of-*> <id-of-D> # "what we changed"
和提交*
之间,&#34;他们&#34; (无论他们是谁,也许是我们)更改了您在A
中删除的文件。
同时,在提交D
和提交*
之间,&#34;我们&#34;删除了文件。请注意,Git在提交D
处甚至无法查看:它只是比较A'
和*
。我们在D
和*
之间以相同的方式更改文件并不重要,唯一重要的是我们在整体更改中删除了文件。
这是合并冲突的根源。介于&#34;他们做了什么&#34;和#34;我们做了什么&#34;,Git不知道是否将更改保留到文件中,或者保留文件的删除。
如果您希望进行合并 - 您可能不会 - 您可以通过运行A'
然后git rm <file>
来提交合并来解决此问题。结果将是一个新的合并提交:
git commit
新合并的树将与提交 A <-- origin/master
/ \
...--o--* \__
\ \
A'-D--M <-- master
的树匹配,但现在您将同时拥有原始提交D
和修改后的副本(使用相同的树但是你历史上不同的提交信息。
您可以将其推送到A
,因为现在如果您向他们发送提交origin
并要求他们将M
设置为指向master
,不会失去承诺M
。
2 差异主要表现在默认的合并提交消息中,大约是,&#34;合并名为master的分支来自远程命名的来源&#34;而不是&#34;合并我们自己的远程跟踪分支origin / master&#34;。此外,如果您有一个古老版本的Git,早于1.8.4,还有一些额外的技术难题,阻止A
在这里工作。希望您不会遇到Git 1.7.x版。
首先,您可以中止正在进行的合并:
origin/master
现在你回到原来的地方了:
git merge --abort
在您的存储库中。
这里的一个大问题是他们,无论他们是谁,在 A <-- origin/master
/
...--o--*
\
A'-D <-- master
上,都提交origin
。你也许可以使用强制推动让他们放弃它:
A
这告诉他们的Git&#34;继续并失去提交git push --force origin master
,只需将A
设置为master
。缺点是,如果他们现在已经获得了一些提交D
和/或B
,那么您也将丢失这些提交。此外,如果其他任何人已获得提交C
的副本,那些其他用户必须执行某些操作才能从重置A
恢复到放弃origin
赞成A
。
您可以使用A'
告诉他们,实际上&#34;我相信您的--force-with-lease
点要提交master
;如果是这样,请改为A
指向master
。&#34; (这要求你的Git和他们的Git都足够新,以便拥有D
选项。)
或者,您可以放弃修改提交消息的想法。只需放弃并移植您的提交--force-with-lease
,使其在D
之后,而不是在A
之后。完全放弃修改后的A'
,为您提供此图表:
A'
您现在可以推送此内容,因为原始 A <-- origin/master
/ \
...--o--* D' <-- master
\
A'-D [abandoned]
的新副本D'
只会添加到其现有提交D
。如果,在这样做之后,我们完全忘记了被遗弃的提交并且更好地绘制了这个,我们得到:
A
这是一段很好的直接历史,也是你所希望的。
使用...--o--*--A--D <-- master, origin
来逃避正在进行的合并后,您的三个选项是:
git merge --abort
到D
,或重复删除以创建D'
,重置自己的D'
指向同一个地方为master
。(如果origin/master
足够私有,那么选项1是安全且容易的。[另外,在正在进行的合并中进行推送在很大程度上是无害的,因为推送仅推送完成的提交。))< / p>
答案 1 :(得分:1)
我认为这就是发生的事情:
要检查这是否是您所处的情况,您可以执行git log
和git log origin/{branchname}
(假设您的远程仓库被称为原产地,并且您将{branchname}替换为分支的名称推到)。远程分支应包含带有旧消息的分支,而本地分支包含新消息。
现在,您在本地提交 B 和 C ,而远程存储库包含提交 A 。执行git pull
时,git会尝试从远程存储库中获取提交 A 。此提交包含对文件MyFile.java的更改。当git尝试将该更改应用于您的本地存储库时,它会识别该文件在此期间已被删除。
更多解释: git根据哈希值识别提交。哈希是基于许多信息计算的,其中包括由该提交完成的差异,先前的提交,消息以及提交的时间。因此,如果您修改提交,则哈希值会更改。在将来,git会将更改前后的提交识别为不同的提交。
您有多种方法可以处理该问题。正如您在此期间评论说回购没有共享但只有您正在使用它,选项2很可能是首选。
git push -f
强制推送您的更改。这将从远程存储库中删除commit A 并推送您的提交 B 和 C 。如果其他人已经从远程存储库中获取了您的更改,这将导致问题,因为他们将遇到您之前遇到的相同问题。git reset --hard A
(注意:如果你还有任何打开的更改,这将删除它们,所以先将它们藏起来)以及之后git cherry-pick C
其中 C 是哈希提交删除文件。如果你做了比那个提交更多的提交,请相应地进行提交(记住它们的哈希值,然后再选择它们)。答案 2 :(得分:0)
您是否在更改提交消息后推送? 在git ammend之后,推动这一变化。然后运行命令删除文件 P.S - 当我按照你提到的步骤
时,我没有遇到这个问题答案 3 :(得分:0)
如果您在修改之前没有推动分支,则意味着其他人在远程主分支上进行了一些更改,并且与修改提交无关。
当你执行pull时,git获取了分支的远程修改,然后尝试将其合并到本地分支中,这个失败导致你删除的文件在其他提交中被修改,所以我猜你需要同步另一个人,看看为什么他们改变了这个文件。
您需要手动解决此冲突。
另一种选择是在远程分支上重新绑定本地分支主服务器,您仍然会遇到冲突,但是您将避免在历史记录中进行合并提交。