如何在分支中创建快照(提交)的副本到git中的另一个分支?

时间:2015-02-18 17:35:41

标签: git

当我开始使用Git时,我了解到的第一件事就是Git不会将信息存储为基于文件的更改(修补程序)列表,而是作为快照流。提交是所有存储库的快照。

考虑我们在存储库Branch_A和Branch_B中有两个分支。无论它们之间的关系如何,它可能非常简单(非常复杂)(与其他分支合并......)。只需代表他们:

A <--- ... -- I <----- J <----- K                Branch_A


       M <------ N <----- O <----- P             Branch_B

由于某些原因,我希望Branch_A的下一次提交完全是Branch_B中提交P的状态(快照)。

是否有git命令来执行此操作?

我无法正常使用&#34;正常&#34;合并,因为我不想解决P和K之间的冲突。 我无法使用选项&#34;他们的&#34;因为它会保留K中与P不冲突的所有文件,即使它们不存在于P.

我可以这样做:

cd /path/to/myrepo;
git checkout Branch_B
cp -R * /path/to/save_branch_b_state
git checkout Branch_A
rm -rf *
cp -R /path/to/save_branch_b_state . (In fact, I copy everything but the .git directory)
git add *
git commit 

但我想有一个git命令可以做到这一点。

3 个答案:

答案 0 :(得分:3)

没有一个单个 git命令可以执行此操作,但只需几个命令即可完成。

第一个问题是:你是否希望这至少类似于一个合并(在这种情况下,它真的会合并)?也就是说,你希望提交图看起来是什么样的 - 如果它显示来自branch_B(提交P生活的地方)的某种联系,那么la:

A <--- ... -- I <----- J <----- K <--- *         Branch_A
                                     /
       M <------ N <----- O <----- P             Branch_B

其中*是您的新提交?或者你想让它完全独立?

低级命令git commit-tree将使用任意父级进行新的提交(您使用-p提供父ID,消息和现有的&#34;树&#34;宾语)。它打印生成的提交对象ID。所以用低级命令来做到这一点:

tree=$(git rev-parse B^{tree})  # or similar to find the tree ID
commit=$(git commit-tree -p ... -m message $tree) # or use -F, or stdin

然后将Branch_A设置为指向$commit(使用git branchgit update-ref)。这可以变成一行shell的东西,因此作为git别名完成,但它有点棘手,可能应该是一个shell脚本。只选择一个ID作为父级,以使新提交成为常规(非合并)提交,或选择多个ID使其成为合并;如果您确实将其合并,请根据您希望将来--first-parent的工作方式选择父ID。

或者,您可以使用更高级别的git命令来执行此操作。例如,如果您不想希望它(并且类似于)合并,您只需从Branch_A开始,擦除所有内容(从索引中删除整个树) work-tree),从commit P重新填充所有内容(根据commit P创建新的索引内容和工作树),然后提交:

$ git checkout Branch_A
$ git rm -rf .                # cd to top dir first if needed
$ git checkout Branch_B -- .  # index and work tree = commit P
$ git commit

或者,将上述内容作为真正的合并:请参阅this question的答案。

答案 1 :(得分:1)

在目的地分行: git cherry-pick <commit id>

答案 2 :(得分:0)

在目标分支工作目录中:

$ rm -rf *
$ git add .
$ git cherry-pick -n -X theirs <COMMIT_ID>
$ git commit --no-edit

对于点(隐藏)文件(rm.*除外),可能需要另外运行.git命令。因为在典型的外壳中,全局模式中的星号(*)符号不会扩展为点文件。