从上游更新时合并冲突

10

我想在Github项目上开始使用git。(我已经使用CVS、SVN和hg多年了,但git很难理解)。我尽可能准确地按照指示操作,但仍然无法使其正常工作。

我克隆了我的分支项目:

git clone git@github.com:davidgiven/linux-allwinner.git

按照建议,我添加了一个“upstream”远程仓库,用于跟踪我所派生的项目:

git remote add upstream https://github.com/amery/linux-allwinner.git

我从中获取:

git fetch upstream

所有这些都很好。但是,自从我fork了这个项目以来已经过去了一个星期左右,上游一直在做改变。所以我想拉取那些更改。我当前在正确的分支---allwinner-v3.0-android-v2---所以我将从上游合并到我的分支:

git merge upstream/allwinner-v3.0-android-v2

...然后我遇到了合并冲突。

CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby/common.h
CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby/Makefile
CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby.S
CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/Makefile
[etc]

现在,我什么也没有提交;我还没有开始工作,我的项目自从我fork它以来一直没有改动。因此不应该有任何冲突。但实际上存在一些冲突;发生了什么,我该如何解决?

更新:

git show-branch HEAD upstream/allwinner-v3.0-android-v2 显示了以下内容,我必须承认我看不懂:

! [HEAD] arm: sun3i: add getioaddr macro
 ! [upstream/allwinner-v3.0-android-v2] arm: sun3i: updated irq handling and machine_desc to 3.0
--
 + [upstream/allwinner-v3.0-android-v2] arm: sun3i: updated irq handling and machine_desc to 3.0
 + [upstream/allwinner-v3.0-android-v2^] arm: sunxi: renable early_printk in all _defconfig except crane's
+  [HEAD] arm: sun3i: add getioaddr macro
+  [HEAD^] arm: sun3i: add dummy machine type

听起来你想要变基而不是合并。 - ThiefMaster
git show-branch HEAD upstream/allwinner-v3.0-android-v2 可能会揭示一些有趣的东西。 - georgebrock
那是来自 show-branch 的完整输出吗?我期望它以一行以“++”开头的行结尾。 - georgebrock
好的,末尾没有 ++ - David Given
2个回答

16

这可能是由于上游重写了历史记录(变基,修订等) - 他们不应该那样做,但你永远不会知道。

既然你说没有任何本地更改或提交,你应该通过重置分支将存储库恢复到干净状态:

git reset --hard upstream/allwinner-v3.0-android-v2

这将丢弃本地所有更改并使当前 HEAD 不可达的提交!


以上假设您将(强制)推送分支的新重置状态到远程仓库,否则当您尝试从 origin 拉取时将再次遇到冲突。

git push origin +allwinner-v3.0-android-v2
如果您已经在本地进行了提交,那么您需要在上游分支之上进行rebase(或cherry-pick),然后将提交推送到origin。这样您就可以像上游一样重写本地历史并将更改应用于顶部。即:
git rebase --onto upstream/branch \
  last-original-upstream-commit-before-yours \
  your-branch

@DavidGiven:git push 到哪里?它会失败,因为你的推送不再是快进的了。你在问题中提到你还没有提交任何东西,所以也许单个强制推送是一个好方法? - knittl
1
schacon.github.com/git/git-rebase.html#_recovering_from_upstream_rebaserebase文档中,有一个完整的章节介绍如何从上游rebase中恢复,如果您想要彻底地了解,这可能会有所帮助。 - ellotheth
2
另外,如果您在答案中添加 push -f,我会接受它。非常感谢。 - David Given
我认为分支名称前面的 + 表示 强制更新 - 至少对我有效 - 或许 -f 也可以? - Chris
2
@Chris:是的,+branchname 表示强制推送。当时(2012年)git push 不支持 -f/--force 选项,后来才添加了该选项。 - knittl
显示剩余8条评论

2
“show-branch” 命令的输出意味着自从它们的共同祖先以来,“upstream” 和 “HEAD” 每个添加了两个提交(假设这是完整的输出)。 (另请参见:http://www.gitguys.com/topics/git-show-branch-to-see-branches-and-their-commits/)如果您自己没有提交任何内容,那么这意味着上游推送了一个变基(或其他更改历史记录的操作)。由于您没有提交任何内容,因此 knittl 的答案正是您想要的。
值得一提的是,我也喜欢使用 “git log --oneline --graph --decorate --remotes --branches” 命令。您将获得一个带有所有分支和远程的 ASCII 图形,因此您可以可视化地了解发生了什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接