My scenario has:
The SVN server is still canonical, but is kept in parity with the GitHub repo. Other users exclusively use SVN, and I am the only git+SVN user (which simplifies things).
When I'm working on other computers (eg my laptop, from home, when abroad) I use git and I push/pull my commits with the GitHub repo. My commits are not put into SVN until I'm in the office.
When I'm in the office I'll do a git pull
to bring-in any new commits from GitHub then do git svn dcommit
, followed by a git push -f
back to GitHub so the newly SVN-annotated commits become canon on GitHub and match SVN perfectly.
However, today I had some pending commits on my office computer - but I also had non-pulled commits too - and I don't know how to fix it.
At 9AM this morning, before running any commands anyhere, my repos looked like this:
o = Normal Git commit, lacking SVN annotation
* = SVN-annotated Git commit
GitHub
*---*---*---*---o---o---o---o---o
A B C D E F G H I
Local computer git repo
*---*---*---*---o---o
A B C D E F
SVN
*---*---*---*
A B C D
Explanation: I had two commits, E
and F
that were in my local computer repo that were previously pulled from GitHub, these commits were not yet dcommit
'd to SVN.
I made a mistake this morning in that I immediately ran git svn dcommit
on my local computer without first running git pull
. Running git svn dcommit
caused the repos to enter this state:
GitHub
*---*---*---*---o---o---o---o---o
A B C D E F G H I
Local computer git repo
*---*---*---*---*---*
A B C D E' F'
SVN
*---*---*---*---*---*
A B C D E' F'
Note that E
and F
are now E'
and F'
because they have been modified by git svn
to be an SVN-annotated commit (so it has a different commit hash, even though it represents the same codebase state). My original E
and F
remain unchanged in GitHub.
My computer does a git fetch
in the background anyway so I now have the GitHub commits E
through I
on my computer, and GitKraken shows me how I now have side-by-side branches that diverge after commit D
:
Local computer git repo:
*---*---*---*---*---* (master)
A B C D E' F'
\
\-o---o---o---o---o (remote-master)
E F G H I
How can I fix this? (As Git-SVN annotated commits are effectively immutable).
I think what I want to do is reparent G
after F'
and so ignore E
and F
, then run git svn dcommit
and then do a git push -f
back to GitHub.
...problem is, I don't know how to reparent G
- I'm looking at commands like cherrypick
but that doesn't seem to be what I'm after, and GitKraken won't let me rebase
(it isn't a menu option for anything in the remote-master
branch).
Can you use command line?
git rebase F I --onto master
Ie rebase commits from after (not including) F up to (including) I onto master.
There are multiple ways that should be fine.
git cherry-pick master..remote-master
will cherry-pick all commits that are in remote-master
but not in master
and as E
and F
introduce the same changes as E'
and F'
, the commits will be empty and you can skip them.
You can of course also directly do
git cherry-pick F..remote-master
git rebase master remote-master
should also work. It tries to apply all commits that are in remote-master
but not in master
onto master
. The commits that do not change anything E'
and F'
should be skipped automatically as their changes are already in that branch.
Alternatively you can of course also do
git rebase --onto master F remote-master
git pull --rebase
should also work just like git rebase master remote-master
.
As you always need a rewritten linear history to talk to the SVN repository cleanly, you should maybe change the configuration so that a pull
automatically does a rebase
and not a merge
. Then you can also produce clean history to dcommit
easily when you do commits on multiple boxes at the same time.
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.