Git:拉一个重新分支

时间:2013-05-27 12:28:43

标签: git push rebase pull

让我描述一下我的情况:

金发先生和奥兰治先生正在研究分支A,它在提交M1的分支机构中分支出来。分支A有2个提交:A1和A2。

M1  
   \
    \
     A1 - A2

与此同时,奥兰治先生承诺并在主分公司M2和M3上再提交了两份承诺。

M1  - M2 - M3
   \
    \
     A1 - A2

布朗先生从遥控器拉出来,过了一会儿决定重新进入主分支:

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1` - A2`

现在A1`和A2`是在金色先生本地存在的重新提交,A1和A2远程存在。金发先生推动他的提交,使用 -f 来强制他的更改并且#34;重写"历史。现在远程存储库看起来像这样:

M1  - M2 - M3
             \
              \
               A1` - A2`

但Orange先生也在A分公司工作。他的本地存储库看起来仍然如下:

M1  - M2 - M3
   \
    \
     A1 - A2

为了与远程存储库中的A分支同步,Orange先生需要做些什么?

正常的拉动不会起作用。 pull -f 会强制远程本地更改吗?我知道删除本地版本的A并从远程存储库再次提供它将会起到作用,但这似乎并不是实现这一目标的好方法。

4 个答案:

答案 0 :(得分:46)

如果Orange先生不介意丢失他的更改,他可以从服务器获取,然后git checkout A2进入他的本地A2分支,然后(假设遥控器被命名为“origin”) )git reset --hard origin/A2A2重置为远程A2所在的位置。

如果他担心丢失更改,他可以合并服务器的更改以解决它们(来自他自己的A2分支,并再次假设该远程被命名为“origin”)git merge origin/A2 。这将创建一个新的提交,它位于他和远程的A2分支之上,并且两者的更改都合并在一起。然后可以将其推回遥控器。

答案 1 :(得分:25)

我的建议(或者,#34;如果我是奥兰治先生,我会做什么?#);从git fetch开始。现在我在我的回购中有这个,这就是金发先生在他的生活之后,就在他跑步之前" git push -f"。

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1' - A2'

一个重要的区别是,我的本地标签A指向rev A2,而远程标签remotes/origin/A指向A2' (布朗先生反过来说,当地标签A指向A2'而remotes/origin/A指向A2)。

如果我一直在处理我的分支副本#34; A"我会改为:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2'

(我的本地标签指向A3而不是A2;或A4或A5等,具体取决于我已应用了多少更改。)现在我所要做的就是改变我的A3(如果需要还有A4等)到A2'。一个明显的直接方式:

$ git branch -a
  master
* A
  remotes/origin/master
  remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A

然后完全降低转速A1和A2,因为修改过的转换为new_A作为A1'和A2'。或者:

$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k

git am -3 -k手册页中描述了git-format-patch方法。

这些确实需要弄清楚金发先生在做rebase之前没有做的事情,即识别A1,A2,A3等。

如果第二种方法成功,我最终得到:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' - A3'

我的分支名称new_A指向A3' (我现有的A分支仍然指向旧的A3)。如果我使用第一种方法并且成功,我最终会得到同样的结果,只是我现有的分支名称A现在将指向A3' (而且我没有A1-A2-A3旧分支的名称,即使它仍然在我的回购中;发现它需要通过reflogs或类似的东西)。

(如果我的A3需要修改成为A3',当然,交互式rebase和" git am"方法都需要我的工作。)

当然也可以只git merge(如Gary Fixler的答案),但这将创建一个合并提交(" M"没有数字,下面并保持转速A1和A2可见,给出:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' -- M
                 \_______________/

如果你想保留原来的A1和A2,这是件好事;如果你想摆脱它们,这是一件坏事。那么"做什么"取决于"你希望结果是什么"。

编辑添加:我更喜欢格式补丁方法,因为它保留了我的旧A分支名称,同时我确保一切都很好。假设一切正常并且 好,这是最后几步:

$ git branch -m A old_A
$ git branch -m new_A A

然后,如果old_A可以完全放弃:

$ git branch -D old_A

或等效地从分支删除开始,然后将new_A重命名为A.

(编辑:另请参阅git rebase --onto文档,了解将A3等转换为new_A分支的目标。)

答案 2 :(得分:2)

出于配置目的,我同时在两个虚拟机上进行开发。结果,我经常在一台计算机上重新建立基础,并且需要将这些更改毫无困难地显示在另一台计算机上。

假设我的分支名为feature/my-feature-branch。在第一个VM上完成重新配置后,我在第二个VM上执行git fetch。出现以下消息:

$ git status
On branch feature/my-feature-branch
Your branch and 'origin/feature/my-feature-branch' have diverged,
and have 21 and 24 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

好吧,不要进行git pull,因为经过一番大惊小怪之后,您最终将无意义地进行合并提交。

相反,运行

git rebase -i origin/feature/my-feature-branch

一旦弹出文本编辑器,请删除所有提交,然后将其替换为以下内容(这样可以完成重新配置,而无需保留任何提交)。

exec echo test

如果确实有需要保留的提交,则可以在此处应用。在这两种情况下,重新配置都将完成,现在两台计算机又重新同步,如以下所示:

$ git pull
Already up-to-date.
$ git push
Everything up-to-date

答案 3 :(得分:0)

TLDR

除非我误解了这个问题,否则橙色先生的答案是git pull --rebase

更长的阅读

简单案例

如果我们假设 A1 和 A2 所做的更改与 A1' 和 A2' 相同(即使它们的提交哈希不相同),那么 Orange 先生可以放弃

M1  - M2 - M3
   \
    \
     A1 - A2

本地拥有

M1  - M2 - M3
             \
              \
               A1` - A2`

无论做什么

git pull --rebase

git branch -d A
git checkout A

一个更有趣的案例

如果我们如上所述假设 A1 和 A2 所做的更改相同并且 Orange 先生进行了额外的提交,那么他将在本地拥有

M1  - M2 - M3
   \
    \
     A1 - A2 - A3O

起源将是

M1  - M2 - M3
             \
              \
               A1` - A2`

再说一次,Orange 先生可以去

M1  - M2 - M3
             \
              \
               A1` - A2` - A3O

用简单的

git pull --rebase

一个更现实的案例

如果我们如上所述假设 A1 和 A2 所做的更改是相同的,Orange 先生进行了额外的提交,Blonde 先生进行了额外的提交,那么 Orange 先生将在本地进行此操作

M1  - M2 - M3
   \
    \
     A1 - A2 - A3O

而且,假设 Blonde 先生已经推动,起源将是

M1  - M2 - M3
             \
              \
               A1` - A2` - A3B

橙色先生可以到达

M1  - M2 - M3
             \
              \
               A1` - A2` - A3B - A3O

做事

git pull --rebase

不过,这一次,他可能需要解决冲突。