I have problems with merging two unconnected git branches. The situation is the following: originally the was a svn repository, at one point a new git repository with the code from svn as an initial commit - without any history was created. And some changes already made etc.
Now i imported the old svn history to this existing repository on a new branch, from-svn
. Now the repository contains one branch, master
, where all the work since switching to the git repository is stored, and one from-svn
where the old commits leading up to the initial commit in the master
are stored. However for git they seem to be unrelated (understandably and of course probably).
Now i want to connect it somehow, to have the complete history on one branch. Is this possible? I tried merging, but i cant. git merge master
(also the other way around) tells me everything is up-to-date (also tried --allow-unrelated-histories
). If specify the most recent commit-id it tells me it is not something we can merge
, even with --allow-unrelated-histories
.
Any ideas?
CodePudding user response:
If there are not many changes in your master
branch, you can try to cherry-pick new commits on top of your from-svn
and then remove master
and rename from-svn
to master
.
CodePudding user response:
I kind of agree with @rukata on this one.... I would use rebase though. So, have a repo that can see both branches (using 2 remotes... or one remote and one local... or 2 local branches? Anyway). When you have that, look for in the branch that has the full history the commit that was used as the first commit of the short branch... let's call this commit A
(use a branch if you want but just the commit ID is fine). Then look for the first commit of the short history and call it B
(and it should have the exact same content as A
... check the differences with git diff A B
but there should be none)..... then run this:
git rebase --rebase-merges B the-short-svn-branch --onto A
That should work.
CodePudding user response:
git rebase and force push
To prepend history of from-svn
into the master branch use git rebase --onto:
git rebase --onto from-svn root-commit-sha master
You can avoid typing the root commit sha using another command git ref-list specifying the commit with no parents:
git rebase --onto from-svn `git rev-list --max-parents=0 master` master
To update the remote (if there is one):
First: read what force-pushing means and does (here's an SO post as a reference) - it's not dangerous but can be disruptive/problematic.
If you're happy to continue:
git checkout master
git push -f
For any colleagues or other working copies to update to the new master:
git checkout master
git fetch
git reset origin/master --hard
For any points of confusion (or wanting to undo a mistake and try again) git reflog is your friend.
Demonstration
Let's setup two branches to simulate the situation in the question:
cd some/empty/folder
git init
git checkout --orphan from-svn
echo "svn added" > README.md
git add README.md
git commit -a -m "svn initial commit"
echo "svn updated" > README.md
git commit -a -m "svn intermediary commit"
echo "svn final" > README.md
git commit -a -m "svn final commit"
git checkout --orphan master
git checkout from-svn README.md
git commit -a -m "import everything from SVN"
echo "git update" > README.md
git commit -a -m "update done via git"
That gives 2 branches, each unrelated to the other:
git log --graph --oneline --all
* c302c8c (HEAD -> master) update done via git
* eff34d4 import everything from SVN
* f518185 (from-svn) svn final commit
* 9f6a5c4 svn intermediary commit
* 6a5ec26 Added readme
Perform the rebase:
git rebase --onto from-svn `git rev-list --max-parents=0 master` master
Successfully rebased and updated refs/heads/master.
And now the branch history looks like so:
* ded996d (HEAD -> master) update done via git
* 9483a1f (from-svn) svn final commit
* abc7c37 svn intermediary commit
* 036d3d7 svn initial commit
Note that the commit ids for the last two commits has changed.