这个Git变基尝试出了什么问题?

时间:2015-10-23 00:15:52

标签: git rebase git-rebase

我正在努力学习如何使用Git“通过本书”。在与多个开发人员合作的项目中,我们共享相同的“origin”远程。我正在一个工作区域开发我的代码,该工作区域与本地git repo不同。

让我们打电话给我的分行br_ysap。我对我的代码进行了更改,并尝试将这些内容引入我的分支,最终引入master分支。自上次同步内容以来,远程master已更新。所以,我想将我的分支重新绑定到当前的主服务器,然后应用我的更新,提交和推送。

这是我正在做的事情和回应:

> git clone ...

> git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

> git checkout br_ysap
Branch br_ysap set up to track remote branch br_ysap from origin.
Switched to a new branch 'br_ysap'

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: SOME-COMMIT-COMMENT
Using index info to reconstruct a base tree...
M       Main/Init.c
M       Main/Main.c
A       Service/Service_1.c
A       Service/Service_2.c
M       build_options.mk
Falling back to patching base and 3-way merge...
Auto-merging build_options.mk
Auto-merging Service/Service_3.c
CONFLICT (content): Merge conflict in Service/Service_3.c
Auto-merging Main/Main.c
CONFLICT (content): Merge conflict in Main/Main.c
Auto-merging Main/Init.c
CONFLICT (content): Merge conflict in Main/Init.c
Failed to merge in the changes.
Patch failed at 0001 SOME-COMMIT-COMMENT
The copy of the patch that failed is found in:
   c:/local_repo/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

过去的某个时间,Service_2.c已重命名为Service_3.c

现在,我在Main.cInit.cService_3.c上收到了“冲突”消息。接下来,我正在解决冲突。检查当前状态:

> git status
rebase in progress; onto fcd827a
You are currently rebasing branch 'br_ysap' on 'fcd827a'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   build_options.mk

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   Main/Init.c
        both modified:   Main/Main.c
        both modified:   Service/Service_3.c

所以,我现在将3个文件从我的工作空间复制到git目录(而不是使用合并工具,并在代码中引入新的更新)。

> cp ../dev-tree/Main/Init.c         Main/Init.c
> cp ../dev-tree/Main/Main.c         Main/Main.c
> cp ../dev-tree/Service/Service_3.c Service/Service_3.c

关注this tutorial后,我会暂存文件:

> git add Main/Init.c Main/Main.c Service/Service_3.c

> git status
rebase in progress; onto fcd827a
You are currently rebasing branch 'br_ysap' on 'fcd827a'.
  (all conflicts fixed: run "git rebase --continue")

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   Main/Init.c
        modified:   Service/Service_3.c
        modified:   build_options.mk

问题1:Main/Main.c发生了什么?为什么会消失?

接下来,按照说明,我继续推销:

> git rebase --continue
Applying: SOME-COMMIT-COMMENT
Applying: SOME-COMMIT-COMMENT - review update
Using index info to reconstruct a base tree...
M       Main/Init.c
Falling back to patching base and 3-way merge...
Auto-merging Main/Init.c
CONFLICT (content): Merge conflict in Main/Init.c
Failed to merge in the changes.
Patch failed at 0002 SOME-COMMIT-COMMENT - review update
The copy of the patch that failed is found in:
   c:/local_repo/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

问题2:为什么Main/Init.c仍然存在冲突?我用新版本覆盖了文件?

检查状态,复制文件,添加和检查状态:

> git status
rebase in progress; onto fcd827a
You are currently rebasing branch 'br_ysap' on 'fcd827a'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   Main/Init.c

no changes added to commit (use "git add" and/or "git commit -a")

> cp ../dev-tree/Main/Init.c Main/Init.c

> git add Main/Init.c

> git status
rebase in progress; onto fcd827a
You are currently rebasing branch 'br_ysap' on 'fcd827a'.
  (all conflicts fixed: run "git rebase --continue")

nothing to commit, working directory clean

据说已准备好完成变基,不是吗?良好:

> git rebase --continue
Applying: SOME-COMMIT-COMMENT - review update
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

> git status
rebase in progress; onto fcd827a
You are currently rebasing branch 'br_ysap' on 'fcd827a'.
  (all conflicts fixed: run "git rebase --continue")

nothing to commit, working directory clean

问题3:什么给了??? 不,我没有忘记git add,谢谢。

当我尝试提交并推送分支时,没有做任何事情:

> git push origin br_ysap:br_ysap
Everything up-to-date

问题4:此变基过程有什么问题?

更新1:关注@ torek的说明,建议我错过了最后的提交步骤,我尝试了rebase --skip。不幸的是,结果是出乎意料的并且过度了:

> git rebase --skip
Applying: ANOTHER_COMMENT
Using index info to reconstruct a base tree...
A       Application/App_3.c
M       CSP/Driver_1.h
M       CSP/Driver_1.c
A       CSP/Driver_2.h
M       CSP/Chip.h
M       Common/Con_1.c
M       Diags/Con_2.c
M       Diags/Makefile
M       Main/Init.c
M       Main/Main.c
M       Main/Makefile
M       OS/Makefile
A       Service/Service_4.h
A       Service/Service_5.h
A       Service/Service_2.c
<stdin>:592: trailing whitespace.
//   $Id$
<stdin>:122074: trailing whitespace.
#define SOME_MOACRO_1
<stdin>:123643: trailing whitespace.
#define SOME_MOACRO_2
<stdin>:128989: trailing whitespace.
#define SOME_MOACRO_3
<stdin>:134620: trailing whitespace.
#define SOME_MOACRO_4
warning: squelched 9 whitespace errors
warning: 14 lines add whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging Service/Service_3.c
CONFLICT (content): Merge conflict in Service/Service_3.c
Auto-merging OS/Makefile
CONFLICT (content): Merge conflict in OS/Makefile
Auto-merging Main/Makefile
CONFLICT (content): Merge conflict in Main/Makefile
Auto-merging Main/Main.c
CONFLICT (content): Merge conflict in Main/Main.c
Auto-merging Main/Init.c
CONFLICT (content): Merge conflict in Main/Init.c
Auto-merging Diags/Makefile
CONFLICT (content): Merge conflict in Diags/Makefile
Auto-merging Diags/Con_2.c
CONFLICT (content): Merge conflict in Diags/Con_2.c
Auto-merging Common/Con_1.c
CONFLICT (content): Merge conflict in Common/Con_1.c
CONFLICT (modify/delete): Application/App_3.c deleted in HEAD and modified in ANOTHER_COMMENT Version ANOTHER_COMMENT of Application/App_3.c left in tree.
Failed to merge in the changes.
Patch failed at 0003 ANOTHER_COMMENT
The copy of the patch that failed is found in:
   c:/local_repo/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

更新2:在执行--skip之前,我复制了目录,以便我可以在更新1之前进行试验。因此,更改为该副本,我尝试{{1}而不是commit --allow-empty。我一直在发现自己看似死路一条:

--skip

看起来分支最终分离了,但没有附加到`

1 个答案:

答案 0 :(得分:4)

在Q1中,发生的事情是您复制的Main/Init.c

  

cp ../dev-tree/Main/Init.c Main/Init.c

(然后git add ed)匹配您重新定位到的树中的版本。

请记住,git rebase通过进入从--onto提交增长的匿名分支起作用 - 这默认为您重新定位的分支提示,在这种情况下是{master的提示1}} - 然后在set-of-commits-to-copy中重复每次提交的git cherry-pick。 (在这种情况下,提交复制是git log master..br_ysap列出的那些。)

您当前的提交(中间或者真正开始的rebase)是git rebase正在构建的匿名分支上的提交。我给分支一个名字,以便更容易看到。事情看起来像这样(我假设原始基数和rebase之间的提交时间很短,所以master部分可能太短,但这个想法应该足够清楚了):

          A - B - C - ... - S  <-- br_ysap
        /
... - o - o - o - T   <-- master, rebase-temp

此处提交T(分支T的{​​{1}} ip),就是您正在重新定位的内容。临时分支指向提交master。提交git当前正在尝试复制(并且失败)是提交T,当rebase告诉git挑选它时,它说要改变A中的内容,但是git不能做出改变。

(如果您在事情发生冲突时获取了应用的提交ID - 此处为Main/Init.c的ID) - 您可以运行A来查看整个提交,或{ {1}}查看一个文件发生了什么。 Git无法将这些更改应用于匿名分支的提示,因此它给您一个冲突错误。)

然后,您将工作树文件(具有冲突标记和所有内容)替换为git show <commit-id>文件。在您添加&#34; ed之后​​,您运行了git show <commit-id> -- Main/Init.c。这将索引 - 您要提交的内容 - 与最新提交的内容进行比较,即提交../dev-tree。如果文件与git status中的文件匹配,则T不会说任何内容。

此时你跑了T。这使得一个新的提交,git自豪地声称它就像承诺一样git status 1 所以我们称之为git rebase --continue

A

Git现在继续使用A'提交 A - B - C - ... - S <-- br_ysap / ... - o - o - o - T <-- master \ A' <-- rebase-temp ,该工作正常,没有冲突 - 您可以看到为什么git cherry-pick原始B并查看内容此时将在git show。无论如何,现在我们有了这个:

B

现在git尝试复制commit rebase-temp。如果你 A - B - C - ... - S <-- br_ysap / ... - o - o - o - T <-- master \ A' - B' <-- rebase-temp 这个提交,你会发现樱桃选择应该对C进行一些新的更改,但git不能做出这些更改:不合适。

所以,git因冲突而停止。您现在应该编辑该文件并对其进行修复,但可能您只需复制并再次添加git show版本(您可以这样做,以便处理Q2和Q3) 。现在你运行Main/Init.c并从git(与Q4相关)得到你的最终投诉:

  

../dev-tree
  git rebase --continue

再次仔细查看提交Applying: SOME-COMMIT-COMMENT - review update,如No changes - did you forget to use 'git add'?所示。我怀疑它只有 更改为C 2 这些更改不会任何提交的内容{{1}因为那个已经有了它们:它们是最后的更改,以使提交git show中的Main/Init.c版本与提交B'中的Main/Init.c版本相匹配}(B的小费)。

这意味着您想要的所有更改都已经存在。您可以强制执行&#34;无需更改&#34;如果要保留空提交,请使用Main/Init.c进行提交,但T不会为您执行此操作。 Rebase更喜欢你说master告诉它,天哪,毕竟不需要提交git commit --allow-empty。然后它将继续进行剩余的提交 - 谁知道有多少提交(你可以找到!) - 并且,如果一切顺利,那么完成它的完成工作,包括移动分支{{1}所以它指向制作的提示最多的提交,我在这里假设git rebase

git rebase --skip-commit

你没有这样做&#34;跳过&#34;步骤,以便rebase仍在进行中,您的分支标签C仍然指向原始提交br_ysap,而不是复制提交S'。因此 A - B - C - ... - S [abandoned] / ... - o - o - o - T <-- master \ A' - B' - D' - ... - S' <-- br_ysap 找不到任何东西。

1 是否 &#34;同样好&#34;取决于您在解决合并冲突时所做的工作有多好。

2 另一种可能性是,它改变了一些其他文件,这些文件与git能够检测到的变化相匹配已经存在,而对于&#34;合并基础&#34;旧br_ysapC加入的位置。我相信你会看到&#34;回归......三方合并&#34;但是,在这种情况下,就是消息。