如何创建反映另一个(发散)分支状态的提交?
How can I create a commit that mirrors the state of another (diverging) branch?
我想提交并将其复制到我的存储库中的其他地方。
现状:
A--B--C--D (branch1)
\
E--F (branch2)
期望的情况:
A--B--C--D--F'(branch1)
\
E--F (branch2)
F 保留在存储库中很重要。我不想重写历史,因为 F 可能是 public.
表示 F 和 F' 的存储库(源代码)的状态应该完全相同。是的,引入的C和D可能会丢失。
我不想在D之上重放E和F。我已经研究了cherry-pick
和rebase
,但他们似乎删除原始提交或简单地重播目标之上的更改。
假设您已经 D
签出。
$ git rm -r .
$ git archive F | tar xf -
$ git add .
$ git commit -m "Duplicate tree of commit F"
第一步将删除所有当前文件,然后您将获取一个存档(git archive
默认为 tar
,h/t 默认为 Marc-François)并立即将其放入你的工作副本。添加所有内容并提交。
这在我的系统上的非常 小测试中有效,因此请彻底测试。
一个解决方案
我有点生疏,但我相信以下方法可以解决问题:
git checkout branch2
git update-ref --no-deref HEAD branch1 # make HEAD to point at the tip of branch1, but keep the working tree from branch2
git checkout branch1 # reattach HEAD to branch1
git commit -m "Some commit message for F'"
回想起来,我认为torek的方法更简单、更安全。特别是 update-ref
can easily be misused.
最小工作示例
# setting things up (output omitted)
mkdir mwe && cd mwe
git init
echo A > README
git add README
git commit -m A
git branch -m branch1
echo B >> README
git commit -a -m B
echo C >> README
git commit -a -m C
echo D >> README
git commit -a -m D
git checkout -b branch2 branch1~2
echo E >> README
git commit -a -m E
echo F >> README
git commit -a -m F
# now...
$ git update-ref --no-deref HEAD branch1
$ git checkout branch1
M README
Switched to branch 'branch1'
$ git commit -a -m "F'"
[branch1 36b29b2] F'
1 file changed, 2 insertions(+), 2 deletions(-)
$ git show
commit 36b29b21cc014ee1ec73ac5dd80a4ad834ee282a (HEAD -> branch1)
Author: xxxxxxxxxxxx
Date: xxxxxxxxxxxxx
F'
diff --git a/README b/README
index 8422d40..04bc76d 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
A
B
-C
-D
+E
+F
这一点是重点,我第一次评论的时候漏掉了:
The state of the repository (source code) represented [by] F and F' should be exactly the same. Yes, what was introduced C and D might be lost.
这种情况下,从git checkout branch2
开始,可以用,不过有一种更简单,还有一种更简单:
$ git rm -r .
$ git checkout <hash-of-F> -- .
$ git commit
其工作原理是从索引中删除所有内容(并将其从工作树中删除)以确保没有来自早期提交的杂散文件保留,然后将提交 F
中的所有内容提取到索引中并开始工作-树,准备提交。
您可以使用以下方法再缩短这一步骤:
$ git read-tree -m -u <hash-of-F>
$ git commit
因为这个 git read-tree
相当于删除和替换。
您可以使用名称 branch1
而不是提交 F
的散列,直到 branch1
本身移动并且不再指向提交 F
.
我想提交并将其复制到我的存储库中的其他地方。
现状:
A--B--C--D (branch1)
\
E--F (branch2)
期望的情况:
A--B--C--D--F'(branch1)
\
E--F (branch2)
F 保留在存储库中很重要。我不想重写历史,因为 F 可能是 public.
表示 F 和 F' 的存储库(源代码)的状态应该完全相同。是的,引入的C和D可能会丢失。
我不想在D之上重放E和F。我已经研究了cherry-pick
和rebase
,但他们似乎删除原始提交或简单地重播目标之上的更改。
假设您已经 D
签出。
$ git rm -r .
$ git archive F | tar xf -
$ git add .
$ git commit -m "Duplicate tree of commit F"
第一步将删除所有当前文件,然后您将获取一个存档(git archive
默认为 tar
,h/t 默认为 Marc-François)并立即将其放入你的工作副本。添加所有内容并提交。
这在我的系统上的非常 小测试中有效,因此请彻底测试。
一个解决方案
我有点生疏,但我相信以下方法可以解决问题:
git checkout branch2
git update-ref --no-deref HEAD branch1 # make HEAD to point at the tip of branch1, but keep the working tree from branch2
git checkout branch1 # reattach HEAD to branch1
git commit -m "Some commit message for F'"
回想起来,我认为torek的方法更简单、更安全。特别是 update-ref
can easily be misused.
最小工作示例
# setting things up (output omitted)
mkdir mwe && cd mwe
git init
echo A > README
git add README
git commit -m A
git branch -m branch1
echo B >> README
git commit -a -m B
echo C >> README
git commit -a -m C
echo D >> README
git commit -a -m D
git checkout -b branch2 branch1~2
echo E >> README
git commit -a -m E
echo F >> README
git commit -a -m F
# now...
$ git update-ref --no-deref HEAD branch1
$ git checkout branch1
M README
Switched to branch 'branch1'
$ git commit -a -m "F'"
[branch1 36b29b2] F'
1 file changed, 2 insertions(+), 2 deletions(-)
$ git show
commit 36b29b21cc014ee1ec73ac5dd80a4ad834ee282a (HEAD -> branch1)
Author: xxxxxxxxxxxx
Date: xxxxxxxxxxxxx
F'
diff --git a/README b/README
index 8422d40..04bc76d 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
A
B
-C
-D
+E
+F
这一点是重点,我第一次评论的时候漏掉了:
The state of the repository (source code) represented [by] F and F' should be exactly the same. Yes, what was introduced C and D might be lost.
这种情况下,从git checkout branch2
开始,可以用
$ git rm -r .
$ git checkout <hash-of-F> -- .
$ git commit
其工作原理是从索引中删除所有内容(并将其从工作树中删除)以确保没有来自早期提交的杂散文件保留,然后将提交 F
中的所有内容提取到索引中并开始工作-树,准备提交。
您可以使用以下方法再缩短这一步骤:
$ git read-tree -m -u <hash-of-F>
$ git commit
因为这个 git read-tree
相当于删除和替换。
您可以使用名称 branch1
而不是提交 F
的散列,直到 branch1
本身移动并且不再指向提交 F
.