Using git to merge two directories with common parent (but different SHA1)
In our project somebody took a copy of the code. They started a new git repository in their directory and continued their work there. Meanwhile the work on our main project repository also continued. We are now left with two git repositories with no common SHA1.
A --- B --- C --- D | | Copy of code to new directory | E --- F --- G
B and E are the exact same files, folders, etc.
Our goal is to use Git to merge changes F and G into the main branch (currently at D)
2 Solutions collect form web for “Using git to merge two directories with common parent (but different SHA1)”
First, I’m going to redraw your diagram.
A --- B --- C --- D master E --- F --- G copy
Let’s first put both of these in the same repo. There are no special steps to this, you just
git fetch both into the same repository.
Then you create a graft. Edit
git filter-branch to make it permanent.
git filter-branch --tag-name-filter cat -- --all
This will create a new history, the “correct” history:
A --- B --- C --- D master \ E --- F --- G copy
After that, you can just merge.
Demo in action
I created two repositories which matched the diagram, copying from commit B to make commit E.
- E has SHA-1
- B has SHA-1
$ git init $ git remote add master ../gittest $ git remote add copy ../gittest2 $ git fetch master remote: Counting objects: 12, done. remote: Compressing objects: 100% (7/7), done. remote: Total 12 (delta 2), reused 0 (delta 0) Unpacking objects: 100% (12/12), done. From ../gittest * [new branch] master -> master/master $ git checkout -b master master/master Branch master set up to track remote branch master from master. Already on 'master' $ git fetch copy warning: no common commits remote: Counting objects: 9, done. remote: Compressing objects: 100% (6/6), done. remote: Total 9 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (9/9), done. From ../gittest2 * [new branch] master -> copy/master $ git log --format=oneline copy/master | tail -n 1 3aa6b69127d20ac42746c39be3c273a9d80fb706 E $ git log --format=oneline master/master 1532332fe705931babe9db04c8d84051867b52c9 D 90903c0ac8dc26649b875ee00ea39bfd7571b1fb C 95b0fc836dbea7eaa0d043390df841d184af7cd5 B e9de90c82a32041cff3a19f8e40d4358bc4ec2ca Commit A $ git log --format=oneline master/master bec0e7af9374e4c57cb87f3fd5b2fb2b6a3f431b G a61e01d096e81c36bcc450afd98ca94cff909622 F 3aa6b69127d20ac42746c39be3c273a9d80fb706 E
What happens if you merge now?
I got merge conflicts that I’d rather auto-resolve.
$ git merge copy/master Auto-merging test.txt CONFLICT (add/add): Merge conflict in test.txt Automatic merge failed; fix conflicts and then commit the result.
Grafts in action
$ echo 3aa6b69127d20ac42746c39be3c273a9d80fb706 \ 95b0fc836dbea7eaa0d043390df841d184af7cd5 > .git/info/grafts $ git filter-branch --tag-name-filter cat -- --all Rewrite bec0e7af9374e4c57cb87f3fd5b2fb2b6a3f431b (7/7) WARNING: Ref 'refs/heads/master' is unchanged Ref 'refs/remotes/copy/master' was rewritten WARNING: Ref 'refs/remotes/master/master' is unchanged $ git merge copy/master Auto-merging test.txt Merge made by the 'recursive' strategy. test.txt | 5 +++++ 1 file changed, 5 insertions(+)
The final result
$ git log --graph --oneline | cat * 4dadb0a Merge remote-tracking branch 'copy/master' |\ | * bb2fc85 G | * be88bc5 F | * 0816baf E * | 1532332 D * | 90903c0 C |/ * 95b0fc8 B * e9de90c Commit A
Assume you are now in the repo include
You need first to add the other repo into this repo use the command.
$git remote add another_repo <git repo path> $git fetch another_repo
Then you can merge, use
$git merge another_repo/master