我对回购有一个奇怪的问题。当我尝试推送我的最新提交时,我不能,即使我很确定我有最新的提交,我是唯一一个在过去几个小时内编辑回购的人。
此外,我的git log 逐行匹配 GitHub上的git log。
$git push
To git@github.com:me/repo_name
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:me/repo_name'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details
这让我想到了以下问题:
注意:我尝试合并,但是我遇到了冲突,所以我因为没想到它们而中止了。我之前正在测试一个实验性的git编辑器,我中途取消了提交(我的回购可能处于某种不一致的状态吗?)。
另外 - 我正在使用git 2.0.2
按照Jubobs的回答,我做了:
$ git log master ..origin/master
它会在git log
中列出确实拥有的一次提交。正如我上面所说,git日志与逐行匹配,我检查了我的源代码,并且我有完全相同的更改,有问题的提交说我没有。怎么会这样?
答案 0 :(得分:5)
对于第1项和第2项,只需使用git fetch
来获取最新的origin/master
(这假设您的github仓库位于名为origin
的远程位置下,并且您没有摆弄同时使用fetch =
行,然后使用任何日志查看器(git log
,gitk
等)向您显示提交内容"他们有"那个"你没有"。有很多方法可以做到这一点。对于完整视图,我个人更喜欢gitk --all
,但git log --graph master origin/master
也会显示一些说明性内容(见下文)。
对于第3项,您可以git push --force
或git push origin +master:master
(同样,这假设origin
是指向github的遥控器的名称。
对于第4项:这是提交图(如第1项所示)有用的地方。让我们说,无论出于何种原因,你将在第1项中看到的图形看起来像这样(除了我想在这里水平绘制它,而不是你在{{1}中得到的垂直图形}):
gitk
在这张特别的图纸中,你提前2&#34;并且&#34;落后于1&#34;。你有两个提交遥控器没有,它有一个你不会提交。或者说,你做有&#34;他们的&#34;提交,但不是通过您的分支名称 --- o - o <-- master
/
... - o - o
\
o <-- origin/master
找到的提交历史记录。
如果你master
,你的git会做什么就是联系他们的(github&#39; s)git和&#34;他们的&#34; repo(即你的repo的github副本),要求它接受你的新提交 - 你git push --force
上不存在的两个 - 然后只是将它们master
指向同样的提交。也就是说,他们的master
现在将指向最右上角(在此图中)提交,这是您master
点的位置。然后你的git会更新他们的git&#39; master
的副本 - 这就是你的git保留在master
中 - 所以你现在拥有的图形如下所示:
origin/master
那&#34;放弃&#34;提交可以从&#34;他们的&#34;回购(即你自己的回购的github副本)几乎立即。
如果其他人也在复制&#34;他们的&#34;回购和使用它的提交,他们可能仍然有被放弃的&#34;提交自己的副本。他们可能会依赖它开始,如果你告诉github忘记提交,他们会感到烦恼,因为现在他们不得不做额外的工作来重新同步,同时还要保留该提交的内容。但是如果没有其他人也在使用这个github副本,或者他们没有拿起那个特定的提交,那么他们永远不会知道那里的提交已经存在并且现在已经被遗弃 - 并且可能真的消失了。
您在编辑中提到您开始 --- o - o <-- master, origin/master
/
... - o - o
\
o [abandoned]
。你是否完成或中止了合并还不清楚。如果你是'#34;在中间&#34;在合并中,您还没有实际创建合并提交,但您应该先完成或中止合并。您可以使用git merge
告诉您是否仍在合并中:
git status
如果你已经中止了合并,那么复制提交给新的(不同的SHA-1哈希,但效果相同)......好吧,让我们重温一下 - 稍微绘制这个图,并给那些提交节点识别字母:
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
[snip]
这里,&#34; prime&#34; --- D - C' <-- master
/
... - A - B
\
C <-- origin/master
中的单引号表示此提交是提交C'
的副本:它具有相同的消息和相同的效果,甚至可能是相同的时间戳;但它有点不同,因为,如果没有别的,它有不同的父提交ID:它指向提交C
,而不是提交D
。
如果强行将其推送到repo的github副本,则会像以前一样放弃提交B
。因为C
已经存在重要的一切,所以没有损失。但它仍然可以为已经克隆了github repo并在C'
之上构建新提交的其他人工作:他们必须改变他们的工作,以便它现在位于C
之上。实际移动应该非常简单(仅C'
),但它仍然有用。
你可以继续强制推动,或者,如果你对这些其他人感到慷慨,你可以尝试重新安排你的自己的工作,这样它就可以了。线性延伸,快速前进&#34;正如git所说的那样。在这种特殊情况下,只需要将提交git rebase
复制到位于D
之上的D'
,然后放弃C
序列以支持新序列:
D - C'
为此,您可以 --- D - C' <-- your old master, to be abandoned
/
... - A - B
\
C <-- origin/master
\
D' <-- this becomes your new master
将git rebase
master
改为origin/master
(有或没有-i
)。 Rebase通常足够聪明,可以注意到复制的提交(C'
)并简单地删除它;或者您可以使用git rebase -i
并自行明确删除它:
$ git checkout master
Already on branch 'master'
$ git rebase origin/master
(或-i
,如上所述)。一旦完成所有工作,您应该可以在没有git push
的情况下--force
:您现在严格地&#34;在#34;之前origin/master
,就是git(以及使用git的人)所期望的。
答案 1 :(得分:4)
1 - 我如何才能看到具体提交的内容与我想要推送的内容相冲突?
执行fetch
,然后假设您的本地仓库知道名为origin
的远程仓库,运行
git log master..origin/master
这将显示可以从origin/master
访问的所有提交,但不会显示在您的本地master
分支中。
2 - 我的
git log
怎么能逐行排列GitHub中的那个并且仍有这个问题?
要查看主分支与origin / master之间的更改,请运行
git diff master origin/master
如果没有输出,请比较两个头的时间戳(master
和origin/master
)。由于SHA-1哈希值不同,必须不同。
3 - 如何强行推动?
运行
git push -f origin master
但等等!
4 - 如果我强行推动会发生什么? (历史会改写吗?)
如果强制将本地master
分支推送到远程,则会强制生成在远程存储库中的master
分支与该本地存储库中的分支完全相同。最近由你的同事推送到远程回购的master
分支上的提交将会消失&#34;从该存储库的历史。这是一个危险的领域。
例如,如果您执行fetch
并且您的本地存储库如下所示,
如果你再运行
git push -f origin master
两个存储库中的master
分支都将指向提交D
:
提交E
和F
将失去&#34;。所以,在强行推动之前三思而后行 ...