I have a Git repo that is clone from another Git repo that is a clone from a giant SVN repo. We can update the other Git repo from SVN and commit from it to SVN, but with another user.
I want to publish my local commits to the SVN repo directly, with my own user.
This is what I tried: I manually created the git-svn
branch, adding this to .git/config
[branch "master"]
[svn-remote "svn"]
url = https://url/to/svn/trunk/repo_name
fetch = :refs/remotes/git-svn
Then git svn fetch
, downloaded 32k commits.
But I ended up with two disjoint histories:
674c35a
that represents the state of the SVN repo at the point of the original clone. master
is always synchronized with SVN (through the other Git repo). dev
have our current developments, that should be merged to master
(usually squashed), and then committed back to the SVN repo. fb1b9c7
] (but only with diff from the previous commits, not the entire repo as a start commit). git/origin/master
. How can I tell Git that the starting commit ( 674c35a
) is actually the same as a SVN commit ( fb1b9c7
)? So Git can somehow understand that the commits in master
, after the clone, are actually the same as git-svn
?
I have tried to rebase with --onto
, as explained here , but that wasn't really what I wanted (the commits are not in top of the branch).
I believe I have a method which should work for this in my blog post Grafting History with Git which for the purposes of complying with site rules I'll summarize here :
Current state :
Target state :
git log --reverse --format="%T %H"
and save this to a file git read-tree -um $TREEID
git commit --reuse-message $ORIGINAL_COMMIT
Or ... cat your list of tree-id + commit-id into this script.
#!/bin/bash # graft script while read TREE COMMIT do git read-tree -um $TREE git commit --reuse-message $COMMIT done
Your history probably looks something like this:
*--*--*--fb1b9c7--*--*--* [git-svn] (version of master from SVN)
674c35a--*--*--* [master] (version of master from Git)
\
*--*--*--* [dev]
It looks like you have two issues: your Git history doesn't contain the 30k+ commits from the full SVN history, and dev
is based off the (incomplete) Git history instead of the SVN version.
Since fb1b9c7
== 674c35a
, you should be able to do:
git rebase --onto git-svn master dev
My experiments indicate that git rebase
doesn't care that the target branch ( git-svn
) doesn't have the same history as the base branch ( master
). It also shouldn't matter that SVN only stores diffs, because git-svn will have converted those diffs into real Git commits during the fetch.
Since the histories contain the same contents, you should even be able to do:
git checkout dev
git rebase git-svn
After that, you can delete master
and let that tree get garbage-collected later. (If you still need a separate master
branch, then do git checkout -b master git-svn
after deleting the original master
.)
When you said:
(the commits are not in top of the branch)
I assume that you are referring to commits fb1b9c7
and 674c35a
. However, it doesn't matter that those commits are buried in the history, because we will choose one ( fb1b9c7
) to use, and let the other be garbage-collected, as mentioned above.
If you want to replace one commit by another commit, just use git replace
, like git replace 674c35a fb1b9c7
.
If you then want to make this permanent, use git rebase
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.