开发者

git: Retroactively introduce several merges

I'm trying to learn git by applying it (retroactively) to a project where I have been tracking a remote codebase for a while. When I put everything into git, I simply made a remote branch for all the external versions and put my versions on master, so currently my repository looks like this:

master: A0---A1.0--A1.1--A2.0--A2.1-....
          \                
remote:    B1----------B2-----------....

My question is: how do I retroactively tell git about the merges that took place, to make the repository look like so (no code should be changed):

master: A0---A1.0--A1.1--A2.0--A2.1-....
         开发者_C百科 \ /           / 
remote:    B1----------B2-----------....

Standard git disclaimer: no published history will be affected by the above actions :)

EDIT: Below is how I did this using grafts as suggested by Kevin:

First, I manually created .git/info/grafts as follows (all entries are sha1's):

A1.0 A0 B1
A2.0 A1.1 B2

Then, after checking that things looked good (gitx), I ran git filter-branch with no arguments.

Filter-branch will make grafts permanent, and store refs to the original commits in refs/originals/... to allow you to back out via git reset --hard refs/originals/refs/heads/master. Since everything looked fine I removed all leftovers as follows:

rm .git/info/grafts
rm .git/refs/originals

If you have garbage collected, you need to do git update-ref -d refs/originals/refs/heads/master instead.


Sounds like you want grafts. You can create grafts for the new merges you want (remember to include the original parent in the graft!), and when everything looks good, use git filter-branch (read the manpage!) to bake it in stone.


You could totally fake this by doing an interactive rebase, specifying that you want to edit all those commits, and amend them with merge commits:

git rebase -i A0 master
# change the lines for A1.0 and A2.0 to "edit"
# git stops at A1.0
git merge --no-commit --strategy=ours B1     # the SHA1 of B1, of course
git commit --amend
git rebase --continue
# git stops at A2.0
git merge --no-commit --strategy=ours B2
git commit --amend
git rebase --continue

Each time you stop, you're technically merging, but with the ours strategy, which keeps all the contents of your current commit. The --no-commit tells git to stop just before committing. You then amend the current commit (which basically means replace) with the merge, instead of making the merge a separate commit as you usually would. Tada! A1.0 has been replaced with a new commit with an identical tree, but an additional parent. commit --amend gives you a chance to edit the message; you may want to do so, to leave some record of what you've done.


I know this is an old question, but there is an updated way of performing this (as of Git 1.6.5).

git replace --graft <commit> <parent1> <parent2>

Where <> are SHA hashes

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜