用 Git 重新定基
Rebasing with Git
我看了很多关于如何使用 Git 变基的文章,这很有意义……或者至少我认为是这样。但是,我正在努力解决以下问题...
对于这个场景,我们有以下分支:
- 大师(本地)
- origin/master
- jheigs(本地)
- origin/jheigs
好的,现在假设 origin/master 领先 1 次提交。因此,文章告诉我,我所在的开发团队将在 jheigs 分支上执行以下操作:
$ git add ...
$ git commit ...
$ git status (ensure everything is up-to-date locally)
$ git pull (again, check and ensure that everything is ready to go)
$ git pull --rebase origin master
$ git push (defaulting to origin/jheigs)
当变基 运行 没问题时,我 运行 进入的是 origin/jheigs 和本地 jheigs 的 HEAD 提交不匹配(给定上面的变基),所以有时我可能不得不先拉然后再推,这可能会导致冲突。我感到困惑的是......我应该改为使用:
$ git push --force origin jheigs (?)
第二个问题...现在,假设我已经推送并且 jheigs 已使用 origin/master 正确地变基。不存在冲突,我的 jheigs 和 origin/jheigs 现在比 master 领先 1 次提交。好的,一天过去了,我需要做更多的改变。所以我对 jheigs 和 add/commit 进行了这些更改。但是,origin/master 没有其他更新。本质上我仍然领先于 origin/master 1 次提交(很快是 2 次)。我是否仍然遵循上述相同的过程?还是我只是 add/commit 并推到 origin/jheigs 而没有变基,因为我已经领先于 origin/master?
很抱歉,这太长了,但我认为我已经弄明白了,但它并不像我想象的那么顺利。我想小心变基,所以任何帮助都将不胜感激!
嗯,首先,我会(并且确实)完全或大部分避免 git pull
:它本来是为了方便,但结果是 in方便的。它只是 运行s git fetch
后跟第二个 Git 命令,它会影响您检出的任何 b运行ch。有时我不想或不需要取回;其他时候,我想看看发生了什么 when fetch 运行, before 我执行任何第二个命令来影响当前b运行ch.
您可能已经读到,git rebase
实际上是关于 复制(一些)提交。您的存储库中有一些提交集合,现在,无论出于何种原因,一些提交已经失去了光彩,您想要更新、更好、更漂亮、更闪亮的提交。
使所有这些都有意义的方法是绘制提交图。请记住,有多个克隆 — 不同的存储库包含 大部分 相同的提交集,但不完全相同的集 — 涉及!
绘制您自己的存储库的提交
您可以让 Git 为您做这件事:git log --all --decorate --oneline --graph
,或 git 记录(与)一只狗。不过,一开始用手做是很好的练习。另外,当你手工画的时候,你可以把它们水平地画出来,这往往更有意义。
请记住,每个由其唯一哈希 ID 标识的提交都是 read-only。每个提交都指向它的 parent 提交。像 master
或 jheigs
这样的 b运行ch 名称,或者像 origin/master
或 origin/jheigs
这样的 remote-tracking 名称, 指向(记录哈希 ID)提示 提交,Git 从这些提示向后工作:
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
这可能是存储库的图形片段,其中提交 E
是 master
的尖端,而 E
指向 D
,而您添加了您自己的两个提交:G
,这是 jheigs
的提示,指向 F
,之前,您添加了 F
指向 [=28] =].
请注意,这里的提交 D
和更早的提交都在 both b运行ches.
A git rebase
将复制 1 一些提交到 new-and-improved 提交。例如,在这里您可能想要将 F
复制到 new-and-improved F'
,其中主要区别在于 F'
附加到 E
,而不是 D
:
F' [new and improved!]
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
将 F
复制到 F'
后,您现在可以将 G
复制到 new-and-improved G'
:
F'-G' [new and improved!]
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
现在所有"on"(可从)jheigs
但不是master
的提交已经复制到 new-and-improved 版本,你可以让 Git 剥离提交 G
上的 jheigs
标签并将其粘贴到 G'
:
F'-G' <-- jheigs (HEAD)
/
...--C--D--E <-- master
\
F--G [abandoned]
旧的、沉闷的 F
和 G
昨天还闪亮漂亮的提交现在变成了垃圾,取而代之的是闪亮的新 F'
和 G'
。这是因为 your b运行ch name jheigs
现在指向最后一个新复制的提交。
1这个复制就像git cherry-pick
完成的一样。根据您使用的变基命令,它实际上可能 是 用 git cherry-pick
完成的。
涉及另一个存储库:fetch
和 push
上图适用于您的 存储库,但此处涉及第二个存储库。他们有自己的 b运行ch 名称和自己的提交。您拥有的提交,他们也拥有,共享提交哈希 ID。可能有一些您拥有但他们没有的承诺;并且可能有一些他们拥有而您没有的提交。
如果您认为他们可能有您没有的承诺,您应该 运行 git fetch
或 git fetch origin
。这让你的 Git 调用他们的 Git,在 URL 你已经列在名字 origin
下。您的 Git 调用他们的 Git 并让他们列出他们的所有提交(通过哈希 ID),这些提交由 他们的 b运行ch 名称给出。
如果他们有您没有的提交,您的 Git 现在会下载这些提交。您的 Git 还 更改 他们的 b运行ch 名称,例如 master
或 jheigs
,以便他们阅读 origin/master
和 origin/jheigs
。这些新名称不会干扰您的 b运行ch 名称。
现在您已经拥有他们拥有的所有提交,加上您之前拥有的所有提交,您的存储库可能看起来像这样——假设您还没有完成git rebase
还:
H <-- origin/master
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD), origin/jheigs
你的origin/*
是你Git对他们b运行ch名字的记忆。这意味着 他们的 master
标识提交 H
。感谢 git fetch
,您现在已经提交了 H
。 他们的 jheigs
标识提交 G
,就像你的一样。
如果您现在 运行 git rebase master
,您的 Git 会将您的 F
和 G
复制到新的 F'
和 G'
,在提交 E
之后构建,这是您的 master
点。您可能希望它们在提交 H
之后出现。
在这里,你可以很容易地做到这一点:你可以 运行 git rebase origin/master
。这告诉您的 Git 找到您拥有的提交(即 F
和 G
),这些提交不是 可从 访问的 origin/master
(即,他们的 master
,就你能记住的程度而言)并在提交 H
之后放置副本。结果如下所示:
F'-G' <-- jheigs (HEAD)
/
H <-- origin/master
/
...--C--D--E <-- master
\
F--G <-- origin/jheigs
请注意,origin/*
个名称中的 none 个已移动,您自己的 master
也没有移动。然而,他们的 jheigs
你称之为origin/jheigs
仍然记得提交G
.
现在你需要git push --force jheigs
,告诉他们:丢弃提交F
和G
支持新的闪亮 F'
和 G'
. 一旦他们同意这样做,您的 Git 就会记住他们的 jheigs
指向 G'
:
F'-G' <-- jheigs (HEAD), origin/jheigs
/
H <-- origin/master
/
...--C--D--E <-- master
由于找不到名字,提交 F
和 G
似乎完全消失了。
为什么你可能永远不想变基
请注意,那里可能有一个 third Git 存储库,还有第四个或更多存储库,其中还有另一个 origin/jheigs
。如果是这样,所有这些 other 存储库必须采取一些行动(例如 运行ning git fetch
)来获取新的提交并更新他们自己的 origin/jheigs
名字。
此外,在您决定放弃您的提交以支持 new-and-improved 之前,他们可能已经在您的提交之上构建了自己的提交。如果是这样,他们可能会被迫复制 他们的 提交,就像您复制自己的一样。这甚至可能是一件好事,也可能会让他们恼火。
因此,如果您打算对 其他人 已经或可能已经完成的提交进行变基,您应该有理由相信可以为他们工作。如果没有其他人拥有原始提交,显然 copy-and-replace 他们是安全的。如果其他人都同意这种 copy-replace 是 应该 发生,那也没关系。因此,如果可以这样做,并且这样做有意义,那么就进行变基。
When the rebase runs fine, what I have run into is that origin/jheigs and local jheigs have HEAD commits that don't match (given the above rebase)
是的,但不同之处在于您的额外 un-pushed 工作。在 git pull --rebase
之后,上游 HEAD 将是您本地 HEAD 的 祖先 。
so at times I may have to pull and then push
这通常是正确的做法
which can cause conflicts.
不应该,除非有人在你的拉和推之间插入(在这种情况下,你需要再做一次,以合并他们的工作)。
Ok, a day goes by and I need to make more changes. So I make those changes on jheigs and add/commit. However, origin/master has no additional updates. Essentially I'm still ahead of origin/master by 1 commits (soon to be 2). Do I still follow the same process above? Or do I just add/commit and push to origin/jheigs without rebasing since I'm already ahead of origin/master?
两者都可以。如果上游没有移动,git pull --rebase
什么都不做。
我看了很多关于如何使用 Git 变基的文章,这很有意义……或者至少我认为是这样。但是,我正在努力解决以下问题...
对于这个场景,我们有以下分支:
- 大师(本地)
- origin/master
- jheigs(本地)
- origin/jheigs
好的,现在假设 origin/master 领先 1 次提交。因此,文章告诉我,我所在的开发团队将在 jheigs 分支上执行以下操作:
$ git add ...
$ git commit ...
$ git status (ensure everything is up-to-date locally)
$ git pull (again, check and ensure that everything is ready to go)
$ git pull --rebase origin master
$ git push (defaulting to origin/jheigs)
当变基 运行 没问题时,我 运行 进入的是 origin/jheigs 和本地 jheigs 的 HEAD 提交不匹配(给定上面的变基),所以有时我可能不得不先拉然后再推,这可能会导致冲突。我感到困惑的是......我应该改为使用:
$ git push --force origin jheigs (?)
第二个问题...现在,假设我已经推送并且 jheigs 已使用 origin/master 正确地变基。不存在冲突,我的 jheigs 和 origin/jheigs 现在比 master 领先 1 次提交。好的,一天过去了,我需要做更多的改变。所以我对 jheigs 和 add/commit 进行了这些更改。但是,origin/master 没有其他更新。本质上我仍然领先于 origin/master 1 次提交(很快是 2 次)。我是否仍然遵循上述相同的过程?还是我只是 add/commit 并推到 origin/jheigs 而没有变基,因为我已经领先于 origin/master?
很抱歉,这太长了,但我认为我已经弄明白了,但它并不像我想象的那么顺利。我想小心变基,所以任何帮助都将不胜感激!
嗯,首先,我会(并且确实)完全或大部分避免 git pull
:它本来是为了方便,但结果是 in方便的。它只是 运行s git fetch
后跟第二个 Git 命令,它会影响您检出的任何 b运行ch。有时我不想或不需要取回;其他时候,我想看看发生了什么 when fetch 运行, before 我执行任何第二个命令来影响当前b运行ch.
您可能已经读到,git rebase
实际上是关于 复制(一些)提交。您的存储库中有一些提交集合,现在,无论出于何种原因,一些提交已经失去了光彩,您想要更新、更好、更漂亮、更闪亮的提交。
使所有这些都有意义的方法是绘制提交图。请记住,有多个克隆 — 不同的存储库包含 大部分 相同的提交集,但不完全相同的集 — 涉及!
绘制您自己的存储库的提交
您可以让 Git 为您做这件事:git log --all --decorate --oneline --graph
,或 git 记录(与)一只狗。不过,一开始用手做是很好的练习。另外,当你手工画的时候,你可以把它们水平地画出来,这往往更有意义。
请记住,每个由其唯一哈希 ID 标识的提交都是 read-only。每个提交都指向它的 parent 提交。像 master
或 jheigs
这样的 b运行ch 名称,或者像 origin/master
或 origin/jheigs
这样的 remote-tracking 名称, 指向(记录哈希 ID)提示 提交,Git 从这些提示向后工作:
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
这可能是存储库的图形片段,其中提交 E
是 master
的尖端,而 E
指向 D
,而您添加了您自己的两个提交:G
,这是 jheigs
的提示,指向 F
,之前,您添加了 F
指向 [=28] =].
请注意,这里的提交 D
和更早的提交都在 both b运行ches.
A git rebase
将复制 1 一些提交到 new-and-improved 提交。例如,在这里您可能想要将 F
复制到 new-and-improved F'
,其中主要区别在于 F'
附加到 E
,而不是 D
:
F' [new and improved!]
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
将 F
复制到 F'
后,您现在可以将 G
复制到 new-and-improved G'
:
F'-G' [new and improved!]
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD)
现在所有"on"(可从)jheigs
但不是master
的提交已经复制到 new-and-improved 版本,你可以让 Git 剥离提交 G
上的 jheigs
标签并将其粘贴到 G'
:
F'-G' <-- jheigs (HEAD)
/
...--C--D--E <-- master
\
F--G [abandoned]
旧的、沉闷的 F
和 G
昨天还闪亮漂亮的提交现在变成了垃圾,取而代之的是闪亮的新 F'
和 G'
。这是因为 your b运行ch name jheigs
现在指向最后一个新复制的提交。
1这个复制就像git cherry-pick
完成的一样。根据您使用的变基命令,它实际上可能 是 用 git cherry-pick
完成的。
涉及另一个存储库:fetch
和 push
上图适用于您的 存储库,但此处涉及第二个存储库。他们有自己的 b运行ch 名称和自己的提交。您拥有的提交,他们也拥有,共享提交哈希 ID。可能有一些您拥有但他们没有的承诺;并且可能有一些他们拥有而您没有的提交。
如果您认为他们可能有您没有的承诺,您应该 运行 git fetch
或 git fetch origin
。这让你的 Git 调用他们的 Git,在 URL 你已经列在名字 origin
下。您的 Git 调用他们的 Git 并让他们列出他们的所有提交(通过哈希 ID),这些提交由 他们的 b运行ch 名称给出。
如果他们有您没有的提交,您的 Git 现在会下载这些提交。您的 Git 还 更改 他们的 b运行ch 名称,例如 master
或 jheigs
,以便他们阅读 origin/master
和 origin/jheigs
。这些新名称不会干扰您的 b运行ch 名称。
现在您已经拥有他们拥有的所有提交,加上您之前拥有的所有提交,您的存储库可能看起来像这样——假设您还没有完成git rebase
还:
H <-- origin/master
/
...--C--D--E <-- master
\
F--G <-- jheigs (HEAD), origin/jheigs
你的origin/*
是你Git对他们b运行ch名字的记忆。这意味着 他们的 master
标识提交 H
。感谢 git fetch
,您现在已经提交了 H
。 他们的 jheigs
标识提交 G
,就像你的一样。
如果您现在 运行 git rebase master
,您的 Git 会将您的 F
和 G
复制到新的 F'
和 G'
,在提交 E
之后构建,这是您的 master
点。您可能希望它们在提交 H
之后出现。
在这里,你可以很容易地做到这一点:你可以 运行 git rebase origin/master
。这告诉您的 Git 找到您拥有的提交(即 F
和 G
),这些提交不是 可从 访问的 origin/master
(即,他们的 master
,就你能记住的程度而言)并在提交 H
之后放置副本。结果如下所示:
F'-G' <-- jheigs (HEAD)
/
H <-- origin/master
/
...--C--D--E <-- master
\
F--G <-- origin/jheigs
请注意,origin/*
个名称中的 none 个已移动,您自己的 master
也没有移动。然而,他们的 jheigs
你称之为origin/jheigs
仍然记得提交G
.
现在你需要git push --force jheigs
,告诉他们:丢弃提交F
和G
支持新的闪亮 F'
和 G'
. 一旦他们同意这样做,您的 Git 就会记住他们的 jheigs
指向 G'
:
F'-G' <-- jheigs (HEAD), origin/jheigs
/
H <-- origin/master
/
...--C--D--E <-- master
由于找不到名字,提交 F
和 G
似乎完全消失了。
为什么你可能永远不想变基
请注意,那里可能有一个 third Git 存储库,还有第四个或更多存储库,其中还有另一个 origin/jheigs
。如果是这样,所有这些 other 存储库必须采取一些行动(例如 运行ning git fetch
)来获取新的提交并更新他们自己的 origin/jheigs
名字。
此外,在您决定放弃您的提交以支持 new-and-improved 之前,他们可能已经在您的提交之上构建了自己的提交。如果是这样,他们可能会被迫复制 他们的 提交,就像您复制自己的一样。这甚至可能是一件好事,也可能会让他们恼火。
因此,如果您打算对 其他人 已经或可能已经完成的提交进行变基,您应该有理由相信可以为他们工作。如果没有其他人拥有原始提交,显然 copy-and-replace 他们是安全的。如果其他人都同意这种 copy-replace 是 应该 发生,那也没关系。因此,如果可以这样做,并且这样做有意义,那么就进行变基。
When the rebase runs fine, what I have run into is that origin/jheigs and local jheigs have HEAD commits that don't match (given the above rebase)
是的,但不同之处在于您的额外 un-pushed 工作。在 git pull --rebase
之后,上游 HEAD 将是您本地 HEAD 的 祖先 。
so at times I may have to pull and then push
这通常是正确的做法
which can cause conflicts.
不应该,除非有人在你的拉和推之间插入(在这种情况下,你需要再做一次,以合并他们的工作)。
Ok, a day goes by and I need to make more changes. So I make those changes on jheigs and add/commit. However, origin/master has no additional updates. Essentially I'm still ahead of origin/master by 1 commits (soon to be 2). Do I still follow the same process above? Or do I just add/commit and push to origin/jheigs without rebasing since I'm already ahead of origin/master?
两者都可以。如果上游没有移动,git pull --rebase
什么都不做。