当我开始使用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命令可以做到这一点。
答案 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 branch
或git 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
命令。因为在典型的外壳中,全局模式中的星号(*
)符号不会扩展为点文件。