如何将父级添加到 git 中的提交?
How do I add a parent to a commit in git?
我最近重新分支 - 也就是说,在 master
之外创建了一个新分支并合并到一个功能分支中,例如TASK-123
,新分支 TASK-123-b
,替换了合并到其中的特性分支。每当功能分支与 master
.
冲突时,这是我们 git 工作流程中的常规操作
当我将TASK-123
合并到TASK-123-b
时,当然有一个合并冲突,我已经解决并提交了。新分支 TASK-123-b
和合并到 TASK-123
的提交只有一个父分支:master
如何修改提交,使 master
和 TASK-123
都是它的父项?我假设 git rebase
会涉及,但除此之外我不知道如何将父 branch/commit 添加到提交中。
我的提交历史目前是这样的:
master -*---*-----* ...
\ \
TASK-123 *---*-* \
\
TASK-123-b * ...
我希望我的提交历史看起来像这样:
master -*---*-----* ...
\ \
TASK-123 *---*-* \
\ \
TASK-123-b \---* ...
注意:我还没有将 TASK-123-b
推送到远程,因此对其进行变基提交应该不会给我的同事带来任何问题。
您需要重新将 TASK-123 合并到 TASK-123-b 中,因为它看起来不像您希望的那样工作。为此,在合并之前在 TASK-123-b 中找到提交哈希,并在那里重置分支指针:
$ git checkout -B TASK-123-b abc123
然后重复合并:
$ git merge TASK-123
如果您重置分支指针,旧的合并提交将被孤立并且不会显示在日志中,除非您特别将其作为参数提及。如果你想找回它,散列将被记录在 reflog 中,或者你可以将散列复制到某个地方,然后在你决定需要时使用 checkout -B
命令将它放回原处。
如果不想再次解决冲突,那就不要重新设置分支指针,重新合并即可:
$ git checkout TASK-123-b
$ git merge TASK-123
并删除旧分支:
$ git branch -d TASK-123
为了便于解释,假设您的提交是这样标识的:
master -a---c-----f-----h ...
\ \
TASK-123 b---d-e \
\
TASK-123-b g---i ...
TL;DR
Rebase,删除合并提交(提交g
),并在合并前编辑提交(提交f
)。
不要在 f
上执行 git commit --amend
,而是执行 git merge e --no-commit
.
使用git checkout g -- .
检查提交g
中的所有文件。
提交并继续变基进程。
详细解答
如果你的提交树可以这样表示:
First,在合并提交之前使用提交哈希第二次变基(合并提交是 g
,因此将使用的提交哈希是 <commit-c-sha>
)
$ git rebase --interactive <commit-c-sha>
这将生成如下待办事项列表:
pick <commit-f-sha> <commit-f-message> -----> change this to edit
pick <commit-g-sha> <commit-g-message> -----> remove this line
pick <commit-i-sha> <commit-i-message>
...
因此您的待办事项列表将如下所示:
edit <commit-f-sha> <commit-f-message>
pick <commit-i-sha> <commit-i-message>
...
其次,创建一个没有提交的合并。
$ git merge <commit-e-sha> --no-commit
在这里,我们实际上不想编辑 提交f
。相反,我们为提交 g
替换准备了一个提交。
这为我们提供了合并提交格式和在合并提交上做一些工作的灵活性(例如:修改文件、修改提交属性等)。
第三次,我们在不移动 HEAD
.
的情况下检出了从提交 g
到当前索引的所有文件
$ git checkout <commit-g-sha> -- .
这确保提交的文件与提交的文件完全相同 g
。
第四,坚持改变并继续变基进程。例如:
$ git commit
$ git rebase --continue
您可以添加任何提交选项(但不要添加 --amend
)或将其替换为 git commit-tree
命令。
在此之后,提交 g
将有两个父项,并且 g
之后的所有提交也都在后面。
master -a---c-----f-----h ...
\ \
TASK-123 b---d-e \
\ \
TASK-123-b \---g---i ... and all of the following commits
备注1:指定时间戳
当您进行提交时,git 默认情况下使用当前时间设置提交日期。如果要指定时间戳,可以检查 GIT_AUTHOR_DATE
& GIT_COMMITTER_DATE
变量和 --date
选项
参考:https://git-scm.com/docs/git-commit#_date_formats
备注2:Commit-Tree(还没试过)
如果您想要一种更灵活的方式来指定提交父级,您可以执行 checkout
并使用 commit-tree
命令而不是 merge
创建提交-> checkout
-> commit
模式。
我最近重新分支 - 也就是说,在 master
之外创建了一个新分支并合并到一个功能分支中,例如TASK-123
,新分支 TASK-123-b
,替换了合并到其中的特性分支。每当功能分支与 master
.
当我将TASK-123
合并到TASK-123-b
时,当然有一个合并冲突,我已经解决并提交了。新分支 TASK-123-b
和合并到 TASK-123
的提交只有一个父分支:master
如何修改提交,使 master
和 TASK-123
都是它的父项?我假设 git rebase
会涉及,但除此之外我不知道如何将父 branch/commit 添加到提交中。
我的提交历史目前是这样的:
master -*---*-----* ...
\ \
TASK-123 *---*-* \
\
TASK-123-b * ...
我希望我的提交历史看起来像这样:
master -*---*-----* ...
\ \
TASK-123 *---*-* \
\ \
TASK-123-b \---* ...
注意:我还没有将 TASK-123-b
推送到远程,因此对其进行变基提交应该不会给我的同事带来任何问题。
您需要重新将 TASK-123 合并到 TASK-123-b 中,因为它看起来不像您希望的那样工作。为此,在合并之前在 TASK-123-b 中找到提交哈希,并在那里重置分支指针:
$ git checkout -B TASK-123-b abc123
然后重复合并:
$ git merge TASK-123
如果您重置分支指针,旧的合并提交将被孤立并且不会显示在日志中,除非您特别将其作为参数提及。如果你想找回它,散列将被记录在 reflog 中,或者你可以将散列复制到某个地方,然后在你决定需要时使用 checkout -B
命令将它放回原处。
如果不想再次解决冲突,那就不要重新设置分支指针,重新合并即可:
$ git checkout TASK-123-b
$ git merge TASK-123
并删除旧分支:
$ git branch -d TASK-123
为了便于解释,假设您的提交是这样标识的:
master -a---c-----f-----h ...
\ \
TASK-123 b---d-e \
\
TASK-123-b g---i ...
TL;DR
Rebase,删除合并提交(提交
g
),并在合并前编辑提交(提交f
)。不要在
f
上执行git commit --amend
,而是执行git merge e --no-commit
.使用
git checkout g -- .
检查提交g
中的所有文件。提交并继续变基进程。
详细解答
如果你的提交树可以这样表示:
First,在合并提交之前使用提交哈希第二次变基(合并提交是 g
,因此将使用的提交哈希是 <commit-c-sha>
)
$ git rebase --interactive <commit-c-sha>
这将生成如下待办事项列表:
pick <commit-f-sha> <commit-f-message> -----> change this to edit
pick <commit-g-sha> <commit-g-message> -----> remove this line
pick <commit-i-sha> <commit-i-message>
...
因此您的待办事项列表将如下所示:
edit <commit-f-sha> <commit-f-message>
pick <commit-i-sha> <commit-i-message>
...
其次,创建一个没有提交的合并。
$ git merge <commit-e-sha> --no-commit
在这里,我们实际上不想编辑 提交f
。相反,我们为提交 g
替换准备了一个提交。
这为我们提供了合并提交格式和在合并提交上做一些工作的灵活性(例如:修改文件、修改提交属性等)。
第三次,我们在不移动 HEAD
.
g
到当前索引的所有文件
$ git checkout <commit-g-sha> -- .
这确保提交的文件与提交的文件完全相同 g
。
第四,坚持改变并继续变基进程。例如:
$ git commit
$ git rebase --continue
您可以添加任何提交选项(但不要添加 --amend
)或将其替换为 git commit-tree
命令。
在此之后,提交 g
将有两个父项,并且 g
之后的所有提交也都在后面。
master -a---c-----f-----h ...
\ \
TASK-123 b---d-e \
\ \
TASK-123-b \---g---i ... and all of the following commits
备注1:指定时间戳
当您进行提交时,git 默认情况下使用当前时间设置提交日期。如果要指定时间戳,可以检查 GIT_AUTHOR_DATE
& GIT_COMMITTER_DATE
变量和 --date
选项
参考:https://git-scm.com/docs/git-commit#_date_formats
备注2:Commit-Tree(还没试过)
如果您想要一种更灵活的方式来指定提交父级,您可以执行 checkout
并使用 commit-tree
命令而不是 merge
创建提交-> checkout
-> commit
模式。