两种git重定基址方法之间的差异
我想执行从主机到我的本地分支的更新,该分支已在时间轴上从主机分支出来(从M2更改)。 Master用两种git重定基址方法之间的差异,git,git-rebase,Git,Git Rebase,我想执行从主机到我的本地分支的更新,该分支已在时间轴上从主机分支出来(从M2更改)。 Master用Mchanges表示,我的本地分支用Lchanges表示 新分支是从master的M2创建的: M1->M2-->M3->M4 \ L1->L2 我想我的结果应该是针对我的本地分支机构,如下所示: M1->M2->M3->M4->L1->L2 这意味着重新创建我的本地分支,使其首先具有所有主更改,然后才在其上具有
M
changes表示,我的本地分支用L
changes表示
新分支是从master的M2
创建的:
M1->M2-->M3->M4
\
L1->L2
我想我的结果应该是针对我的本地分支机构,如下所示:
M1->M2->M3->M4->L1->L2
这意味着重新创建我的本地分支,使其首先具有所有主更改,然后才在其上具有我的本地分支更改,如:(如果我错了,请纠正我) 我的问题是,以下方法之一是否没有创建上述所需的流,如果是,为什么
git checkout master
git pull --rebase
git checkout branch_to_update
git rebase master` (method mentioned in attlasian tautorial)
VS
假设这两种情况具有相同的效果
在第一种情况下,您正在更新主文件的本地副本,然后重新定基
在第二种情况下,您直接从远程存储库重定基址
当您可能不想费心更新要从中重定基址的分支的本地副本时,请使用第二个选项
例如,我们有一个maindevelope
分支,我们将其作为主题分支,例如,feature/0001
。工作时,我会不时检查feature/0001
并简单地git pull-r origin develope
。在这种情况下,拥有develope
的本地最新副本是不相关的
合并我的功能分支后,我签出并拉取development
,然后从更新的副本创建一个新的feature/0002
分支
此外,请注意,它实际上会产生以下结果:
M1 -> M2 -> M3 -> M4 -> L1' -> L2'
我所说的L1'
是什么意思?大致上,它将创建一个具有相同内容的新提交(具有新的SHA标识符)。因此,它本身并不相同
或
这是相同的结果,但方式不同
pull--rebase
参数简单地使用rebase与其他两个答案一样,效果基本相同。但还有更多。为了了解原因和原因,我们应该将git-pull分解为它的组成部分
所有挑剔的细节(警告:长)
除了一些小的例外(例如在完全空的存储库中运行它),git pull
意味着:
使用各种选项和参数运行git fetch
;然后
运行第二个Git命令,该命令在运行步骤1之前选择,并带有各种选项和参数
第二个命令通常是gitmerge
,但是您可以告诉git使用gitrebase
。传递给这两个命令的选项和参数取决于传递给git pull
的选项和其他配置设置,以及步骤1中获取的一个或多个结果
不过,作为一种一般规则,传递给git pull
的参数被传递给git fetch
,因此这意味着传递origin master
到git pull
的第二个命令序列也将origin master
传递给git fetch
。如果在没有这些参数的情况下运行git pull
,就像在第一个命令序列中一样,git会从您的配置中提取远程(通常是origin
)和上游分支名称(通常与当前分支名称相同),特别是从这两个命令的结果中:1
(其中,$branch
是当前分支)。如果当前分支为master
,则将使用branch.master.remote
作为远程分支。这就是我们假设只有一个遥控器的意思。merge
名称可能是master
,但如果不是,那是我们必须做出的另一个假设,然后才能声称它们做同样的事情
1如果您的Git足够大,Git pull
是一个shell脚本,它可以运行各种其他Git命令。如果是较新的,git pull
已转换为C语言程序,并直接内置这些程序
重新设置副本的基础,然后切换到新副本
如果我们深入研究所有细节,git-rebase
所做的事情会变得复杂,但在较高的层次上,它的工作是复制提交。要查看它将复制哪些提交,您应该绘制提交图,或者使用git log--graph
让git为您绘制提交图。(有些GUI总是绘制它,有些web界面*cough*GitHub*cough*从不让您查看!)使用图形绘制,很容易,有时也很容易判断复制了哪些提交:
...--A--B--C--D <-- master
\
E--F--G <-- br
现在我们可以看到,我们必须将br
重新设置到origin/master
上,以便副本在提交D
之后进行。重新定位到master
将把副本放在B
之后,这就是原件所在的位置,因此根本不需要复制。(例如,重设基址是实际复制,还是仅仅重新使用原件,是一个很挑剔的细节:这取决于-f
选项。)
复制完成后,git-rebase
只需将分支名称重新指向最终复制(或重复使用)的提交,我们可以在这里调用G'
,以注意它是G
的副本。虽然HEAD和原始分支的reflog条目以及名称ORIG_HEAD
临时保留它们,但原始提交实际上已被放弃:
E'-F'-G' <-- br
/
C--D <-- origin/master
/
...--A--B <-- master
\
E--F--G [abandoned, but see ORIG_HEAD and reflogs]
这将把我们的头
连接到我们的主机
,检查提交B
;然后,假设上游是origin/master
,运行git fetch origin master
更新我们的origin/master
,在这种情况下,origin/master
指向D
。如果我们没有运行git fetch
,这将获得提交C
和D
,并将我们的origin/master
指向D
最后,它将运行git-rebase
。rebase操作使用哈希I
git checkout branch_to_update
git pull --rebase origin master
git config --get branch.$branch.remote
git config --get branch.$branch.merge
...--A--B--C--D <-- master
\
E--F--G <-- br
C--D <-- origin/master
/
...--A--B <-- master
\
E--F--G <-- br
E'-F'-G' <-- br
/
C--D <-- origin/master
/
...--A--B <-- master
\
E--F--G [abandoned, but see ORIG_HEAD and reflogs]
git checkout master
git pull --rebase
git checkout br
git rebase master
E'-F'-G' <-- br (HEAD)
/
...--A--B--C--D <-- master, origin/master
\
E--F--G [abandoned]
git checkout br
git pull --rebase origin master
E'-F'-G' <-- br
/
C--D <-- origin/master
/
...--A--B <-- master
\
E--F--G [abandoned]
git fetch origin master
git checkout <whatever-name>
git rebase origin/<whatever-other-name>