Lars Schneider
Lars Schneider

Reputation: 5692

Stitch two independent branch histories together

I have two independent branches in my Git repository:

A---B---C branch "old"
X---Y---Z branch "master"

I want to generate the following history:

A---B---C---X---Y---Z

I tried this with the following rebase command (current branch is "master"):

git rebase --strategy=recursive --strategy-option=theirs old master

This fails with:

First, rewinding head to replay your work on top of it...
fatal: Could not parse object 'fb56e6e20ea4a605503732df1f5a0a407808dffa^'

fb56e6 is the first commit of the "old" branch.

As an alternative I used the cherry pick command (current branch is "master"):

git rev-list --reverse old | git cherry-pick --stdin --keep-redundant-commits -X theirs

This works fine, but all commits get a new "committer". Is there a way to tell cherry pick that it should not set the committer? If not, is there a way to achieve what I want with rebase?

Upvotes: 3

Views: 192

Answers (3)

Guildenstern
Guildenstern

Reputation: 3771

If you just want to rebase an unrelated history on top of another one:

git switch master
git rebase --root --onto old

Notice the error message:

First, rewinding head to replay your work on top of it...
fatal: Could not parse object 'fb56e6e20ea4a605503732df1f5a0a407808dffa^'

fb56e6e...^ means that it tried to get the first parent of fb56e6e, but that commit doesn’t exist since fb56e6e is a root commit.

Preserving committer

This one is more fun.

git switch master
git rebase --root --onto old --exec 'git -c committer.name="$(git log -1 --pretty=format:%cn)" -c committer.email="$(git log -1 --pretty=format:%ce)" commit --amend --no-edit'

But what about preserving the committer date?

Left as an exercise for the reader.

Upvotes: 0

Lars Schneider
Lars Schneider

Reputation: 5692

I solved it using git filter-branch:

FIX_COMMITTER='
    if test "$GIT_AUTHOR_NAME" != "$GIT_COMMITTER_EMAIL"; then
        GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
        GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
        export GIT_COMMITTER_EMAIL
        export GIT_COMMITTER_NAME
    fi
'
git filter-branch -f --env-filter "$FIX_COMMITTER" -- master

Source of the idea: https://gist.github.com/maciej/5875814

Upvotes: 2

G. Sylvie Davies
G. Sylvie Davies

Reputation: 5517

I like your cherry-pick approach. Just run the standard "set my author info" commands before doing cherry-pick to match the "commiter" data you want to preserve.

git config --global user.name "John Doe"
git config --global user.email [email protected]

And then set the author info back to yourself when you're done.

Upvotes: 1

Related Questions