【问题标题】:git rebase basicsgit rebase 基础知识
【发布时间】:2012-07-19 14:44:09
【问题描述】:

我最近开始使用git rebase,但我不能 100% 确定我做得对。为了这个问题,起源有两个分支,masternext,它们是从master分支出来的。

自上次在两者之间同步以来,master 有 2 次提交,next 6:

$ git log --oneline origin/next..origin/master
59b5552 master commit #2
485a811 master commit #1

$ git log --oneline origin/master..origin/next
4ebf401 next commit #6
e9b6586 next commit #5
197ada0 next commit #4
4a2c3c6 next commit #3
040a055 next commit #2
84537bf next commit #1

当我结帐next 并执行git rebase -i origin/master 时,我得到以下信息:

$ git status
# On branch next
# Your branch and 'origin/next' have diverged,
# and have 8 and 6 different commits each, respectively.

最后在完成git pull --rebase 之后,来自master 的两个提交都在next 中:

$ git log --oneline origin/next..next 
8741d09 master commit #2
485a811 master commit #1

问题:

  1. 这是正确的方法吗?
  2. 为什么在运行 pull --rebase 之前会有 8 and 6 不同的提交?
  3. 是否可以简化流程?

非常感谢:)

【问题讨论】:

  • 嗨,大卫,您的意思是 git pull --rebase 而不是 git rebase --pull
  • @MikeSep 你是正确的,已修复,谢谢。

标签: git git-rebase


【解决方案1】:

让我们从头开始。这是您原始状态的图表:

A-B-C(主控,原点/主控) \ D-E-F-G-H-I(下一个,起源/下一个)

当您签出next 并将next 重新定位到origin/master 时,它在origin/master 上已经存在的两个提交之后创建了6 个新提交。这些新提交以“master commit #2”(我的图表中的C)作为它们的祖先,而不是它们的原始祖先,origin/masterorigin/next 出现分歧(我的图表中的A),所以它们的哈希值会有所不同.我相信这就是为什么您会看到 nextorigin/next 有 8 个不同的提交:origin/master 的 2 个和 origin/next 上的 6 个“重新散列”提交。

git checkout next ; git rebase -i origin/master 之后,你应该有这个:

A-B-C(主控,原点/主控) \ \ \D'-E'-F'-G'-H'-I'(下) \ D-E-F-G-H-I(原点/下一个)

您可以看到 next 确实有 8 个提交不在 origin/next 上,origin/next 确实有 6 个提交不在 next 上。当然,这只是根据提交的 SHA-1 哈希值。如果您git diff origin/next next,实际内容应该非常匹配——差异应该只显示来自BC 的更改(如图所示)。

当您在next 上执行git pull --rebase 时,它会从源(远程origin/next)获取更改并将当前分支(next)重新定位到该远程。这会导致next 中的更改不是origin/next 中出现在origin/next 之后的新next 分支上。它应该是这样的:

A-B-C(主控,原点/主控) \ D-E-F-G-H-I(原点/下一个) \ B'-C'(下一个)

如果这是您希望历史图表的样子,那么您就成功了。

但是,我怀疑您确实希望看起来像中间图,特别是如果 next 是您正在处理项目的下一个部分的功能分支,而 master 用于稳定代码和小错误修复。如果是这样,那么您应该使用git push 而不是git pull --rebase 来使遥控器反映您的历史版本,而不是相反。

【讨论】:

  • 我假设git rebase --pull 很像git pull --rebase。它先获取然后是git rebase @{u} 嗯,这是一个谎言,但这是一种简单的思考方式。但关键是您的本地分支被重置为 @{u} ,然后在重置之前旧分支上的所有本地提交都在上游所拥有的之上重播。这允许一个微不足道的快进向上游推送。
  • 假设git rebase --pull 是一个错字并且应该是git pull --rebase,那么我认为这会将next 重新排序为D'-E'-F'-G'-H'-I'-B'-C'。听起来对吗?如果是这样,我会相应地编辑我的答案。
  • git pull --rebase 之后你会得到 A-D-E-F-G-H-I-B'-C'。 g-p-r 将始终强制您的本地分支 (next) 包含 @{u} (origin/next) 上的所有提交,然后任何对 next 唯一的内容都将在顶部重播(可能是樱桃挑选的)。恭喜 git 足够聪明,不会尝试创建 D"-E"-F"-G"-H"-I"
  • 真的很抱歉打错了,应该是git pull --rebase。谢谢你的解释,我现在明白发生了什么。我做的流程正确吗? git rebase 然后git pull --rebase 还是有其他方法?
  • @DavidKuridža:没有特别的理由说明您需要执行任一命令。如果下一个是在 ADEFGHI 并且您的目标是 ADEFGHIB'C' 那么您需要运行的唯一命令是 git checkout next; git cherry-pick ...master
【解决方案2】:

从非常简单的步骤开始,用 master 重新定位你的分支; 姓名;

git-rebase

概要;

git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
        [<upstream>] [<branch>]
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
        --root [<branch>]
git rebase --continue | --skip | --abort | --edit-todo

说明; 假设存在以下历史并且当前分支是“sample”:

 A---B---C sample
         /
    D---E---F---G master

从此时开始,以下任一命令的结果:

git rebase master
git rebase master sample

应该是:

A'--B'--C' sample
                 /
    D---E---F---G master

注意:后一种形式只是git checkout sample 后跟git rebase master 的简写。当 rebase 退出时,sample 将保留已签出的分支。

如果上游分支已经包含您所做的更改(例如,因为您邮寄了一个应用于上游的补丁),那么该提交将被跳过。例如,在以下历史记录上运行“git rebase master”(其中 A 和 A 引入了相同的更改集,但具有不同的提交者信息):

A---B---C sample
         /
    D---E---A'---F master

将导致:

 B'---C' sample
              /
D---E---A'---F master

所有这些都是对变基过程的图解理解。 一旦您解决了键入git rebase master 后发现的冲突 解决冲突并键入git add -u 以将更改的代码添加到存储库。 之后执行命令git rebase --continue 并继续解决冲突并重复命令;

git add -u 

git rebase --continue 

直到没有发现冲突。 最后的最终命令将是,

git push --force origin sample(your branch name)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-04-16
  • 2018-05-25
  • 2014-11-28
  • 2014-02-14
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多