software:svnsyncgit
Differences
This shows you the differences between two versions of the page.
— | software:svnsyncgit [2021/05/14 22:23] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Creating a two-way SVN <> GitHub sync ====== | ||
+ | ===== Intro ===== | ||
+ | |||
+ | When migrating [[pdclib: | ||
+ | |||
+ | As Erin Shepherd pointed out in one of the many emails we exchanged, Git seems to have pretty much won the Version Control battle. I still much prefer Subversion, but I realize that being present on GitHub would certainly not hurt the project. | ||
+ | |||
+ | But that meant keeping the Subverion repo and the GitHub repo in sync... and Erin was quite certain that '' | ||
+ | |||
+ | There were multiple how-to' | ||
+ | |||
+ | In the end, I figured a write-up that is //not// missing one or two crucial steps would be nice, so I did one. | ||
+ | |||
+ | ===== Initial Setup ===== | ||
+ | |||
+ | So I had the SVN repo at '' | ||
+ | |||
+ | I did set up an GitHub account and a [[https:// | ||
+ | |||
+ | ===== Get a local clone ===== | ||
+ | |||
+ | This is easy: | ||
+ | |||
+ | < | ||
+ | git clone git@github.com:/ | ||
+ | </ | ||
+ | |||
+ | You need to have copied your SSH pubkey to your GitHub account for this kind of authorization to work (click on your avatar in the top-right corner, select " | ||
+ | |||
+ | Change into the freshly cloned Git Directory: | ||
+ | |||
+ | < | ||
+ | cd pdclib | ||
+ | </ | ||
+ | |||
+ | ===== Tell Git about SVN ===== | ||
+ | |||
+ | Now we tell Git that there is another repository which we want to fetch data from (a.k.a. " | ||
+ | |||
+ | < | ||
+ | git svn init -s svn:// | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | ===== Map the authors ===== | ||
+ | |||
+ | Subversion logs commits with the user's login name. For Git, '' | ||
+ | |||
+ | < | ||
+ | solar = Martin Baute < | ||
+ | erin = Erin Shepherd < | ||
+ | cycl0ne = cycl0ne < | ||
+ | </ | ||
+ | |||
+ | ===== Fetch the data ===== | ||
+ | |||
+ | Now we can fetch all the revision data from Subversion. For this, we need '' | ||
+ | |||
+ | < | ||
+ | git svn fetch --authors-file=authors.txt | ||
+ | </ | ||
+ | |||
+ | If '' | ||
+ | |||
+ | After this step is complete (which might take a while), the latest Subversion information is available to Git. | ||
+ | |||
+ | ===== Git Branches ===== | ||
+ | |||
+ | Let's set up the '' | ||
+ | |||
+ | < | ||
+ | git branch --no-track shepherd | ||
+ | </ | ||
+ | |||
+ | I selected '' | ||
+ | |||
+ | ===== Sync Branches ===== | ||
+ | |||
+ | Now here comes the trick. Git users do not really like '' | ||
+ | |||
+ | We set up //two additional branches// for the //sole purpose// of synchronizing SVN <> GIT: | ||
+ | |||
+ | < | ||
+ | git branch --no-track trunksvn | ||
+ | git branch --no-track shepherdsvn | ||
+ | </ | ||
+ | |||
+ | Then we link up both of these branches to their respective SVN remote. (This is where Ben Lobaugh' | ||
+ | |||
+ | < | ||
+ | git checkout trunksvn | ||
+ | git reset --hard remotes/ | ||
+ | </ | ||
+ | |||
+ | If you look at the contents of your directory, you will now see the '' | ||
+ | |||
+ | Make sure that everything is up-to-date (which it will be anyway at this point, but get into the habit early). We are talking to Subversion again, so '' | ||
+ | |||
+ | < | ||
+ | git svn rebase | ||
+ | </ | ||
+ | |||
+ | Now switch to the //target// branch, and merge in the sync branch. We need to tell Git explicitly that it is OK to merge '' | ||
+ | |||
+ | < | ||
+ | git checkout master | ||
+ | git merge trunksvn --allow-unrelated-histories | ||
+ | </ | ||
+ | |||
+ | We do the same thing for the second branch-to-be-synced: | ||
+ | |||
+ | < | ||
+ | git checkout shepherdsvn | ||
+ | git reset --hard remotes/ | ||
+ | git svn rebase | ||
+ | git checkout shepherd | ||
+ | git merge shepherdsvn --allow-unrelated-histories | ||
+ | </ | ||
+ | |||
+ | ===== Push Branches ===== | ||
+ | |||
+ | We can now push the '' | ||
+ | |||
+ | < | ||
+ | git push --set-upstream origin shepherd | ||
+ | </ | ||
+ | |||
+ | Then we switch to our local '' | ||
+ | |||
+ | < | ||
+ | git checkout master | ||
+ | git push | ||
+ | </ | ||
+ | |||
+ | Any Git user cloning our GitHub repo now will see //only// '' | ||
+ | |||
+ | ===== Sync SVN -> Git ===== | ||
+ | |||
+ | To update the Git repo with changes made to SVN, we follow these steps (in our local clone directory which **does** have the SVN remote and the sync branches): | ||
+ | |||
+ | < | ||
+ | git checkout trunksvn | ||
+ | git svn rebase | ||
+ | git checkout master | ||
+ | git merge trunksvn | ||
+ | git push origin master | ||
+ | </ | ||
+ | |||
+ | Or, for the '' | ||
+ | |||
+ | < | ||
+ | git checkout shepherdsvn | ||
+ | git svn rebase | ||
+ | git checkout shepherd | ||
+ | git merge shepherdsvn | ||
+ | git push origin shepherd | ||
+ | </ | ||
+ | |||
+ | ===== Sync Git -> SVN ===== | ||
+ | |||
+ | To update the SVN repo with changes made to Git, we follow these steps (in our local clone directory which **does** have the SVN remote and the sync branches): | ||
+ | |||
+ | < | ||
+ | git checkout master | ||
+ | git pull origin master | ||
+ | git checkout trunksvn | ||
+ | git svn rebase | ||
+ | git merge --no-ff master | ||
+ | git commit | ||
+ | git svn dcommit | ||
+ | </ | ||
+ | |||
+ | Or, for the '' | ||
+ | |||
+ | < | ||
+ | git checkout shepherd | ||
+ | git pull origin shepherd | ||
+ | git checkout shepherdsvn | ||
+ | git svn rebase | ||
+ | git merge --no-ff shepherd | ||
+ | git commit | ||
+ | git svn dcommit | ||
+ | </ | ||
+ | |||
+ | ===== Re-Building ===== | ||
+ | |||
+ | If, for some reason, you lose that Git setup created above, you need to re-build it: | ||
+ | |||
+ | < | ||
+ | git clone git@github.com:/ | ||
+ | cd pdclib | ||
+ | git svn init -s svn:// | ||
+ | </ | ||
+ | |||
+ | Now you need to re-build the '' | ||
+ | |||
+ | < | ||
+ | commit 5950958ff57391789d9a164a56cd1ed87dedaa12 (HEAD -> master, origin/ | ||
+ | Merge: 02e56d5 ec5835f | ||
+ | Author: Martin Baute < | ||
+ | Date: Tue Feb 2 10:59:34 2021 +0100 | ||
+ | |||
+ | Merge branch ' | ||
+ | |||
+ | commit ec5835f129d8f9629d334657d4c31b40d6190724 | ||
+ | Author: solar < | ||
+ | Date: Mon Feb 1 21:15:12 2021 +0000 | ||
+ | |||
+ | git-svn-id: https:// | ||
+ | ^^^ | ||
+ | </ | ||
+ | |||
+ | A bit easier is to have the computer extract the number for you: | ||
+ | |||
+ | < | ||
+ | REVISION=$(git log | grep git-svn-id | head -n1 | sed -e " | ||
+ | </ | ||
+ | |||
+ | Now fetch everything from your SVN repository //up to that revision//: | ||
+ | |||
+ | < | ||
+ | git svn fetch -r0: | ||
+ | </ | ||
+ | |||
+ | Set up the sync branch, and link it to the SVN remote: | ||
+ | |||
+ | < | ||
+ | git branch --no-track trunksvn | ||
+ | git checkout trunksvn | ||
+ | git reset --hard remotes/ | ||
+ | </ | ||
+ | |||
+ | Now rebase the branch //to what you already fetched//. The '' | ||
+ | |||
+ | < | ||
+ | git svn rebase --local | ||
+ | </ | ||
+ | |||
+ | Now we merge the sync branch to our master. This is basically a no-op, but it sets the merge point from which we will proceed. | ||
+ | |||
+ | < | ||
+ | git checkout master | ||
+ | git merge trunksvn --allow-unrelated-histories | ||
+ | </ | ||
+ | |||
+ | Now we are set up again, and can sync the SVN revisions we left out previously by the " | ||
+ | |||
+ | < | ||
+ | git checkout trunksvn | ||
+ | git svn rebase | ||
+ | git checkout master | ||
+ | git merge trunksvn | ||
+ | git push origin master | ||
+ | </ | ||
+ | |||
+ | ===== Conclusion ===== | ||
+ | |||
+ | I hope this little how-to helps you settling the holy VCS war. |