Git:拉取一个重新定位的分支
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16773249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Git: Pulling a rebased branch
提问by Itai Hanski
Let me describe my situation:
我描述一下我的情况:
Mr Blond and Mr Orange are working on branch A that branches out of the master branch on commit M1. Branch A has 2 commits: A1 and A2.
Mr Blond 和 Mr Orange 正在分支 A 上工作,该分支在提交 M1 时从主分支分支出来。分支 A 有 2 个提交:A1 和 A2。
M1
\
\
A1 - A2
Meanwhile, Mr Orange committed and pushed 2 more commits on the master branch, M2 and M3.
与此同时,Orange 先生在主分支 M2 和 M3 上提交并推送了另外 2 个提交。
M1 - M2 - M3
\
\
A1 - A2
Mr Blond pulls from the remote, and after a while decides to rebase onto the master branch:
Mr Blond 从遥控器中拉出,一段时间后决定重新设置到 master 分支上:
M1 - M2 - M3
\ \
\ \
A1 - A2 A1` - A2`
Now A1` and A2` are the rebased commits that exist locally at Mr blond's, and A1 and A2 exist remotely. Mr Blond pushes his commits, using -fto force his changes and "rewrite" history. Now the remote repository looks like this:
现在 A1` 和 A2` 是存在于 Mr blond's 本地的 rebase 提交,而 A1 和 A2 存在于远程。金发先生推动他的提交,使用-f来强制他的更改并“重写”历史。现在远程存储库看起来像这样:
M1 - M2 - M3
\
\
A1` - A2`
But Mr. Orange worked on the A branch as well. His local repository still looks like this:
但Orange 先生也在A 分店工作。他的本地存储库仍然是这样的:
M1 - M2 - M3
\
\
A1 - A2
What does Mr. Orange need to do in order to be synchronized with A branch in the remote repository?
橘子先生需要做什么才能与远程仓库中的A分支同步?
A normal pull won't work. Will pull -fforce the changes from the remote locally? I know that deleting the local version of A and bringing it again from the remote repository will do the trick but that doesn't seem to be a good way to achieve that.
正常的拉动是行不通的。将拉-f强制远程本地从变化?我知道删除 A 的本地版本并将其从远程存储库中重新引入会解决问题,但这似乎不是实现这一目标的好方法。
采纳答案by torek
My recommendation (or, "what I would do if I were Mr Orange") is, start with git fetch
. Now I'll have this in my repo, which is what Mr Blond had after his rebase and just before he ran "git push -f".
我的建议(或者,“如果我是 Orange 先生,我会怎么做”)是,从git fetch
. 现在我将把这个放在我的 repo 中,这是 Blond 先生在他的 rebase 之后和他运行“git push -f”之前所拥有的。
M1 - M2 - M3
\ \
\ \
A1 - A2 A1' - A2'
The one important difference is, I'll have my local label A
pointing to rev A2, and the remote label remotes/origin/A
pointing to A2' (Mr Blond had it the other way around, local label A
pointing to A2' and remotes/origin/A
pointing to A2).
一个重要的区别是,我的本地标签A
指向 rev A2,远程标签remotes/origin/A
指向 A2'(Blond 先生相反,本地标签A
指向 A2' 并remotes/origin/A
指向 A2)。
If I've been working on my copy of the branch named "A" I'll have this instead:
如果我一直在处理名为“A”的分支的副本,我将改为:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2'
(with my local label pointing to A3 rather than A2; or A4 or A5, etc, depending on how many changes I have applied.) Now all I have to do is rebase my A3 (and A4 if needed, etc) onto A2'. One obvious direct way:
(我的本地标签指向 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
and then drop revs A1 and A2 entirely, since the modified ones are in new_A as A1' and A2'. Or:
然后完全降低转速 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
(the git am -3 -k
method is described in the git-format-patch
manual page).
(该git am -3 -k
方法在git-format-patch
手册页中有描述)。
These do require figuring out what I have that Mr Blond didn't before he did his rebase
, i.e., identifying A1, A2, A3, etc.
这些确实需要弄清楚我有什么,而金发先生在做他的之前没有rebase
,即识别 A1、A2、A3 等。
If the second approach is successful I end up with:
如果第二种方法成功,我最终会得到:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' - A3'
where my branch name new_A
points to A3' (my existing A
branch still points to the old A3). If I use the first approach and it succeeds, I end up with the same thing, it's just that my existing branch name A
will now point to A3' (and I have no name for the old branch with A1-A2-A3, even though it's still in my repo; finding it requires going through reflogs or similar).
我的分支名称new_A
指向 A3'(我现有的A
分支仍然指向旧的 A3)。如果我使用第一种方法并且它成功了,我最终会得到同样的结果,只是我现有的分支名称A
现在将指向 A3'(并且我没有 A1-A2-A3 的旧分支的名称,即使它仍然在我的仓库中;找到它需要通过 reflogs 或类似的东西)。
(If my A3 needs modification to become A3', both the interactive rebase and the "git am" method will require work by me, of course.)
(如果我的 A3 需要修改为 A3',当然,交互式 rebase 和“git am”方法都需要我的工作。)
Of course it's also possible to just git merge
(as in the answer by Gary Fixler), but that will create a merge commit ("M" with no number, below) and keep revs A1 and A2 visible, giving:
当然,也可以只git merge
(如 Gary Fixler 的回答),但这将创建一个合并提交(“M”没有数字,下面)并保持 A1 和 A2 转速可见,给出:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' -- M
\_______________/
If you want to preserve the original A1 and A2, this is a good thing; if you want to get rid of them, it's a bad thing. So "what to do" depends on "what you want the result to be".
如果你想保留原来的A1和A2,这是一件好事;如果你想摆脱它们,这是一件坏事。所以“做什么”取决于“你想要的结果是什么”。
Edit to add: I like the format-patch method better as it leaves my old A branch name around while I make sure everything is good. Assuming it all works and isgood, here's the last few steps:
编辑添加:我更喜欢 format-patch 方法,因为它在我确保一切正常的同时保留了我的旧 A 分支名称。假设所有的工作,并为好,这里是最后几个步骤:
$ git branch -m A old_A
$ git branch -m new_A A
and then, if old_A can be abandoned entirely:
然后,如果可以完全放弃 old_A:
$ git branch -D old_A
or, equivalently, start with the branch delete, then rename new_A to A.
或者,等效地,从分支删除开始,然后将 new_A 重命名为 A。
(Edit: see also git rebase --onto
documentation, for the goal of rebasing A3, etc., onto the new_A branch.)
(编辑:另请参阅git rebase --onto
文档,以将 A3 等重定位到 new_A 分支上。)
回答by Gary Fixler
If Mr. Orange doesn't mind losing his changes, he can fetch from the server, then git checkout A
to get onto his local A
branch, then (presuming the remote is named "origin") git reset --hard origin/A
to reset his A
to where the remote's A
is.
如果 Orange 先生不介意丢失他的更改,他可以从服务器获取,然后git checkout A
进入他的本地A
分支,然后(假设远程名为“origin”)git reset --hard origin/A
将其重置A
为远程所在的A
位置。
If he is concerned with losing changes, he can merge the server's changes in to resolve them (from his own A
branch, and presuming again that the remote is named "origin") with git merge origin/A
. This will make a new commit that's on top of both his and the remote's A
branches with the changes from both merged together. Then this can be pushed back to the remote.
如果他担心丢失更改,他可以合并服务器的更改以解决它们(来自他自己的A
分支,并再次假设远程名为“origin”)git merge origin/A
。这将在他和远程A
分支的顶部进行一个新的提交,并将两者的更改合并在一起。然后可以将其推回遥控器。
回答by theMayer
I develop concurrently on two virtual machines, for configuration purposes. As a result, I frequently rebase on one machine and need the changes to appear on the other without difficulty.
我在两台虚拟机上同时开发,用于配置目的。因此,我经常在一台机器上变基,并且需要毫无困难地将更改显示在另一台机器上。
Suppose my branch is named feature/my-feature-branch
. After finishing the rebase on the first VM, I do a git fetch on the second. The following message appears:
假设我的分支名为feature/my-feature-branch
。在第一个 VM 上完成 rebase 后,我在第二个 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)
Well, don't do a git pull, because then you end up with a meaningless merge commit after quite a bit of fussing.
好吧,不要执行 git pull,因为在经过一番大惊小怪之后,您最终会得到一个毫无意义的合并提交。
Instead, run
相反,运行
git rebase -i origin/feature/my-feature-branch
git rebase -i origin/feature/my-feature-branch
Once the text editor pops up, delete all commits, and replace it with the following (this makes it so the rebase completes without any commits being kept).
一旦文本编辑器弹出,删除所有提交,并将其替换为以下内容(这使得 rebase 完成而不保留任何提交)。
exec echo test
exec echo test
If you do have commits that need to be kept, then those can be applied here. In either case, the rebase will complete, and now both machines are in sync again, as evidenced by:
如果您确实有需要保留的提交,那么可以在此处应用这些提交。在任何一种情况下,rebase 都会完成,现在两台机器再次同步,如下所示:
$ git pull
Already up-to-date.
$ git push
Everything up-to-date