让我描述一下我的情况:
金发先生和奥兰治先生正在研究分支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并从远程存储库再次提供它将会起到作用,但这似乎并不是实现这一目标的好方法。
答案 0 :(得分:46)
如果Orange先生不介意丢失他的更改,他可以从服务器获取,然后git checkout A2
进入他的本地A2
分支,然后(假设遥控器被命名为“origin”) )git reset --hard origin/A2
将A2
重置为远程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)
除非我误解了这个问题,否则橙色先生的答案是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
不过,这一次,他可能需要解决冲突。