git:分支分歧;如何继续?

47

我的本地代码与主代码分岔了:

$ git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 7 and 3 different commit(s) each, respectively.
#
nothing to commit (working directory clean)

我尝试了git pull --rebase但失败了:

$ git pull --rebase
First, rewinding head to replay your work on top of it...
Applying: * ...
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging ChangeLog
CONFLICT (content): Merge conflict in ChangeLog
Failed to merge in the changes.
Patch failed at 0001 * ...
我使用git rebase --abort回滚了,现在回到了起点。
我的目标是:
1. 将我的7个补丁导出为人类可读的diff文件(类似于hg export)。 2. 让我的树成为原始主干的副本(类似于hg strip)。 3. 逐个手动重新应用我的7个补丁(类似于hg import)。
我知道git rebase --continue可以实现此操作。 我已经这样做了,并且它确实起作用了(经过几次手动合并和 git add)。 但是,我想手动完成这个过程, 因此,我想知道与上述hg命令相对应的git命令是什么。
谢谢。
PS。请不要告诉我使用带有gitChangeLog文件很愚蠢。 即使是这样,也不由我决定。

  1. git合并 origin/master。
  2. git拉取 --no-rebase。由于您的提交很大,不进行rebase的拉取会更容易些。
- Abhinav Manchanda
4个回答

54

当然,您可以手动完成这个过程的几种方式。您仍然会遇到相同的冲突,因为git基本上是在幕后为您执行此操作。但是如果您想要手动执行此操作,则有两种方法。

首先,将您的提交导出为一系列补丁。最简单的方法是使用git format-patch

git format-patch -M @{upstream}

这将产生7个补丁文件,每个文件对应一个提交记录。(注意"@{upstream}"是字面意思,它是git不太知名的功能。) 这比捕获git diff的输出更好,因为所有提交信息(作者、日期、消息等)都得以保留。

接下来,你可以重置你的仓库以匹配上游:

git reset --hard @{upstream}

然后,您可以使用git am重新应用补丁--一次一个或一次全部。

git am 0001-blah-blah.patch
git am 0002-blah-blah.patch
...

第二种选择是创建一个备用分支,将您的工作放在其中:

git branch scrap

然后将你的分支重置为上游分支:

git reset --hard @{upstream}

然后使用cherry-pick选取提交记录:

git cherry-pick scrap~6
git cherry-pick scrap~5
git cherry-pick scrap~4
...

然后删除 scrap 分支:

git branch -D scrap

4
你可以使用"@{u}"来代替"@{upstream}"。 - Pat Notz
这是非常高效和干净的 - 最终你会得到一个线性的历史记录。 - hauron
我还没有尝试过这个。有人可以解释一下为什么会起作用吗? - learning2learn
注意:git reset --hard 命令会删除未提交的修改。也许将当前工作区保存到 stash 而不是新建一个分支更为可取。 - dmcontador

26

你尝试过 git merge origin/master 吗?

你的远程更改被存储在分支 origin/master 中。(如果你执行了 git fetch,它就会存在)只需要像其他两个分支一样合并两个分支 - masterorigin/master - 并解决冲突(如果有的话)。

如果你需要知道如何解决git冲突,这可能对你有所帮助。

如何解决Git中的合并冲突?


点赞。我遇到了完全相同的问题,而这个解决方法修复了它。个人不太喜欢vi或vim,所以我将默认编辑器更改为nano。可以谷歌搜索相关指示。 - Cocoadelica

6
Git表示它试图按照您的意愿(在origin/master的最新更改之上重新应用您的补丁),但由于冲突而失败。在git pull --rebase之后,编辑器将打开具有冲突的文件(git status会在“both changed”下列出这些文件),并使用标准diff语言解决冲突。解决冲突后,使用git rebase --continue(如果您的解决方案没有引入更改,则使用git rebase --skip)命令。
阅读有关此内容的信息,请访问Stackexchange文档“解决Git rebase后的合并冲突”

Git在合并(或自动解决“冲突”)和重新应用补丁方面非常出色,但有时它需要您的帮助。在这些情况下,根据我的经验,我不知道还有哪个工具能做得更好。您真的需要手动解决这些冲突。 - wilhelmtell
好的建议 -- 一定要查看 git rerere - Pat Notz
这并没有回答问题。 - sds
@sds 我觉得没问题了。当你合并分支,解决了合并冲突,并在主分支上重放了你的更改后,一切都回归正常了。这就是Wilhelmtell所描述的情况。 - Philipp Claßen

1

以下是一些解决同样问题的好方法(但不包括冲突解决):

主分支和“origin/master”已经分叉,如何“合并”分支?

首先,您可能需要查看远程主分支与本地版本之间的差异:

git log HEAD..origin/master

为了解决您实际的问题,归根结底,与Wilhelmtell提出的相同。
git pull --rebase

正如你所说,你会遇到冲突。

解决冲突是一个经常出现的问题。如果你还没有尝试过,可以看一下 git mergetool(详情请参见 git help mergetool)。为了获得图形化支持,我建议覆盖 merge.tool 配置。例如,如果你想使用 meld 进行三方合并,可以使用以下命令:

git config --global merge.tool meld

所以在你解决了冲突之后,git pull --rebase 做了什么呢?它将所有来自 origin/master 的更改合并到你的本地 master 分支,并在其之上重放了你的更改。恭喜,你又回到了正常状态。


当执行命令 "git pull --rebase" 时,它会显示 "error: feeding unmodified ... to diffcore Cannot pull with rebase: Your index contains uncommitted changes. Please commit or stash them" 错误,但是当执行 "git commit" 命令时,它会显示 "Your branch and 'origin/master' have diverged, and have 1 and 1 different commit each, respectively. (use "git pull" to merge the remote branch into yours) nothing to commit, working directory clean"。 - diyism

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