Git: 如何更新 merge-base 创建的分支
Git: how to update branch made by merge-base
假设我有 2 个分支:v1.0
和 development
。
我们的过程是使用以下方法创建本地分支:
git merge-base v1.0 development
git checkout <commit-hash>
git checkout -b <new-branch-name>
假设我的一位同事遵循相同的流程并最近进行了更改:
git checkout v1.0
git merge <his-local-branch-name>
git push
git checkout development
git merge <his-local-branch-name>
git push
我的问题是,如何使用他最近的更改轻松地更新我的本地分支?
我所做的是使用 merge-base 创建另一个包含最近更改的分支,并将其与我在本地所做的更改合并。
但是否存在一些简单的方法?我在考虑 git merge <last-commit-hash>
之类的东西,但它会产生很多冲突。
好吧...所以听起来 development
是代表以前版本的长期分支 - 很像 gitflow 中的 master
。
听起来 v1.0
是一个长期存在的分支,您可以在其中组装下一个版本,很像 gitflow 中的 develop
。
并且给定的本地分支可能类似于功能分支(在这种情况下,您会将其合并到 v1.0
)或类似于修补程序(在这种情况下,您将其合并到两者 v1.0
和 development
)。奇怪的是,您似乎总是创建本地分支,以便它们 可以 合并到两者。 (所以你不知道,在创建分支时,你是否会合并到 development
?因为如果不是这种情况,那么在合并基础上使每个分支 "start over" 似乎都有一些不必要的合并解决成本...但我离题了。)
让我们通过图片逐步了解您的场景。您从
开始
A -- x <--(development)
\
Z <--(v1.0)
然后你创建一个本地分支
A -- x <--(development)
|\
| Z <--(v1.0)
\
B -- C <--(feature)
并且您的同事创建了本地分支机构
A -- x <--(development)
|\
| x -- O <--(hotfix)
|\
| Z <--(v1.0)
\
B -- C <--(feature)
(请耐心等待;我意识到可能永远不会有一个包含所有这些分支的回购协议,但无论如何我们只看一下 "big picture"...)
所以你的同事合并到两个长期存在的分支
A -- x -- M <--(development)
|\ /
| x --- O <--(hotfix)
|\ \
| Z ----- M <--(v1.0)
\
B -- C <--(feature)
请注意,从现在开始,O
是 development
和 v1.0
的合并基础。但是您的分支是在合并基础 A
时创建的,所以现在我们来回答您的问题:如何将 hotfix
放入您的分支。
到目前为止 hotfix
是共享历史不可或缺的一部分,因此您可能不想做任何重写 and/or 复制其提交的更改的事情。
您可能不想将 v1.0
合并到您的分支中,因为将 Z
混合到您的分支中似乎 运行 与在合并基地。
所以你真的只想将 O
合并到你的分支中。现在让我们换个角度,看看你的本地仓库会如何看待事物,如果我按字面意思理解你的术语 "local branches" (意味着你没有 hotfix
分支):
A -- x -- M <--(development)
|\ /
| x --- O
|\ \
| Z ----- M <--(v1.0)
\
B -- C <--(feature)
现在,鉴于 feature
也是 也是 本地的(仅存在于您的存储库中),一种选择是将其重新设置为新的合并基础 - 这似乎就像它保留在您的工作流程中一样。
git rebase $(git merge-base development v1.0) feature
会给你
A -- x -- M <--(development)
|\ /
| x --- O -- B' -- C' <--(feature)
\ \
Z ----- M <--(v1.0)
此时B'
和C'
都是代码的未测试状态。理想情况下,您应该同时测试它们并解决任何问题(不过,如果 B'
中存在问题,那说起来容易做起来难),这样您仍然会有一个干净的历史记录。
另一个选项可以避免 "untested commits" 问题,但会创建 "messier"(虽然可以说更准确)历史记录,是简单地将合并基础合并到您的分支中。
git checkout feature
git merge $(git merge-base v1.0 development)
这给你类似的东西
A -- x -- M <--(development)
|\ /
| x --- O -----------
|\ \ \
| Z ----- M <--(v1.0) \
\ \
B -- C -------------- M <--(feature)
其中,在走了很长一段路要说 "why" 之后,意味着我们基本上做了您已经做过的事情,只是跳过了为合并创建分支的步骤,因为我们可以只引用合并基础直接。
这是有道理的。您已经弄清楚要与您的分支合并的更改 - 您真的 不想 更改您正在合并的提交。所以我们能做的就是找到一种更简单的方法来引用这些更改。
What I did, was to create another branch with recent changes using merge-base and merge it with my changes made locally.
这是一种方法 (Mark illustrates the rebase approach )
但并非如此,有了 Git 2.22(2019 年第 2 季度),您将不必做:
git merge-base v1.0 development
git checkout <commit-hash>
git checkout -b <new-branch-name>
相反,你会这样做:
git checkout -b <new-branch-name> v1.0...development
参见 commit e3d6539, commit 27434bf (27 Apr 2019) by Denton Liu (Denton-L
)。
Helped-by: Junio C Hamano (gitster
).
(由 Junio C Hamano -- gitster
-- in commit 4ac8371 合并,2019 年 5 月 19 日)
branch
: make create_branch
accept a merge base rev
When we ran something like
$ git checkout -b test master...
it would fail with the message
fatal: Not a valid object name: 'master...'.
This was caused by the call to create_branch
where start_name
is
expected to be a valid rev.
However, git checkout
allows the branch to
be a valid merge base rev (i.e. with a "...
") so it was possible for
an invalid rev to be passed in.
Make create_branch
accept a merge base rev so that this case does not
error out.
As a side-effect, teach git-branch how to handle merge base revs as
well.
假设我有 2 个分支:v1.0
和 development
。
我们的过程是使用以下方法创建本地分支:
git merge-base v1.0 development
git checkout <commit-hash>
git checkout -b <new-branch-name>
假设我的一位同事遵循相同的流程并最近进行了更改:
git checkout v1.0
git merge <his-local-branch-name>
git push
git checkout development
git merge <his-local-branch-name>
git push
我的问题是,如何使用他最近的更改轻松地更新我的本地分支?
我所做的是使用 merge-base 创建另一个包含最近更改的分支,并将其与我在本地所做的更改合并。
但是否存在一些简单的方法?我在考虑 git merge <last-commit-hash>
之类的东西,但它会产生很多冲突。
好吧...所以听起来 development
是代表以前版本的长期分支 - 很像 gitflow 中的 master
。
听起来 v1.0
是一个长期存在的分支,您可以在其中组装下一个版本,很像 gitflow 中的 develop
。
并且给定的本地分支可能类似于功能分支(在这种情况下,您会将其合并到 v1.0
)或类似于修补程序(在这种情况下,您将其合并到两者 v1.0
和 development
)。奇怪的是,您似乎总是创建本地分支,以便它们 可以 合并到两者。 (所以你不知道,在创建分支时,你是否会合并到 development
?因为如果不是这种情况,那么在合并基础上使每个分支 "start over" 似乎都有一些不必要的合并解决成本...但我离题了。)
让我们通过图片逐步了解您的场景。您从
开始A -- x <--(development)
\
Z <--(v1.0)
然后你创建一个本地分支
A -- x <--(development)
|\
| Z <--(v1.0)
\
B -- C <--(feature)
并且您的同事创建了本地分支机构
A -- x <--(development)
|\
| x -- O <--(hotfix)
|\
| Z <--(v1.0)
\
B -- C <--(feature)
(请耐心等待;我意识到可能永远不会有一个包含所有这些分支的回购协议,但无论如何我们只看一下 "big picture"...)
所以你的同事合并到两个长期存在的分支
A -- x -- M <--(development)
|\ /
| x --- O <--(hotfix)
|\ \
| Z ----- M <--(v1.0)
\
B -- C <--(feature)
请注意,从现在开始,O
是 development
和 v1.0
的合并基础。但是您的分支是在合并基础 A
时创建的,所以现在我们来回答您的问题:如何将 hotfix
放入您的分支。
到目前为止 hotfix
是共享历史不可或缺的一部分,因此您可能不想做任何重写 and/or 复制其提交的更改的事情。
您可能不想将 v1.0
合并到您的分支中,因为将 Z
混合到您的分支中似乎 运行 与在合并基地。
所以你真的只想将 O
合并到你的分支中。现在让我们换个角度,看看你的本地仓库会如何看待事物,如果我按字面意思理解你的术语 "local branches" (意味着你没有 hotfix
分支):
A -- x -- M <--(development)
|\ /
| x --- O
|\ \
| Z ----- M <--(v1.0)
\
B -- C <--(feature)
现在,鉴于 feature
也是 也是 本地的(仅存在于您的存储库中),一种选择是将其重新设置为新的合并基础 - 这似乎就像它保留在您的工作流程中一样。
git rebase $(git merge-base development v1.0) feature
会给你
A -- x -- M <--(development)
|\ /
| x --- O -- B' -- C' <--(feature)
\ \
Z ----- M <--(v1.0)
此时B'
和C'
都是代码的未测试状态。理想情况下,您应该同时测试它们并解决任何问题(不过,如果 B'
中存在问题,那说起来容易做起来难),这样您仍然会有一个干净的历史记录。
另一个选项可以避免 "untested commits" 问题,但会创建 "messier"(虽然可以说更准确)历史记录,是简单地将合并基础合并到您的分支中。
git checkout feature
git merge $(git merge-base v1.0 development)
这给你类似的东西
A -- x -- M <--(development)
|\ /
| x --- O -----------
|\ \ \
| Z ----- M <--(v1.0) \
\ \
B -- C -------------- M <--(feature)
其中,在走了很长一段路要说 "why" 之后,意味着我们基本上做了您已经做过的事情,只是跳过了为合并创建分支的步骤,因为我们可以只引用合并基础直接。
这是有道理的。您已经弄清楚要与您的分支合并的更改 - 您真的 不想 更改您正在合并的提交。所以我们能做的就是找到一种更简单的方法来引用这些更改。
What I did, was to create another branch with recent changes using merge-base and merge it with my changes made locally.
这是一种方法 (Mark illustrates the rebase approach
但并非如此,有了 Git 2.22(2019 年第 2 季度),您将不必做:
git merge-base v1.0 development
git checkout <commit-hash>
git checkout -b <new-branch-name>
相反,你会这样做:
git checkout -b <new-branch-name> v1.0...development
参见 commit e3d6539, commit 27434bf (27 Apr 2019) by Denton Liu (Denton-L
)。
Helped-by: Junio C Hamano (gitster
).
(由 Junio C Hamano -- gitster
-- in commit 4ac8371 合并,2019 年 5 月 19 日)
branch
: makecreate_branch
accept a merge base revWhen we ran something like
$ git checkout -b test master...
it would fail with the message
fatal: Not a valid object name: 'master...'.
This was caused by the call to
create_branch
wherestart_name
is expected to be a valid rev.
However,git checkout
allows the branch to be a valid merge base rev (i.e. with a "...
") so it was possible for an invalid rev to be passed in.Make
create_branch
accept a merge base rev so that this case does not error out.As a side-effect, teach git-branch how to handle merge base revs as well.