Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is git svn rebase required before git svn dcommit?

Tags:

git

git-svn

I'm reading about using git as an svn client here:

http://learn.github.com/p/git-svn.html

That page suggests that you do git svn rebase before git svn dcommit, which makes perfect sense; it's like doing svn update before doing svn commit. Then, I started looking at the documentation for git svn dcommit (I was wondering what the 'd' is about):

http://git-scm.com/docs/git-svn

You have to scroll down a bit to see the documentation on dcommit, which says this:

Commit each diff from a specified head directly to the SVN repository, and then rebase or reset (depending on whether or not there is a diff between SVN and head).

This confuses me, because if you do as the first page says, there will be no changes to pull down from svn once the first part of dcommit finishes.

I'm also confused by the part that talks about reset; isn't git reset for removing changes from the staging area?

Why would rebase or reset follow (the first part of) a dcommit?

like image 346
allyourcode Avatar asked Apr 22 '10 23:04

allyourcode


1 Answers

Disclaimer: I generally do tend to run git svn rebase before doing a git svn dcommit. I usually keep my changes in another git branch, so that the rebase doesn't have any chance of failing. I use git rebase master in my topic branch to bring it up to date. Then I switch to the master branch and use git merge to incorporate the changes from my topic branch into master (this is a fast-forward due to the rebase).

My explanation below explains why this isn't mechanically necessary, but I do agree that it's a good idea to do. Your changes might not cause conflicts in terms of diffs and merging, but if you dcommit your code without getting the latest changes from svn and reviewing their effects, you could be committing code to svn that doesn't really do the right thing.


You don't have to git svn rebase before running git svn dcommit. If the modifications you want to dcommit are in files that haven't changed in svn since you last fetched changes, then git-svn won't show a conflict. In this way, you could be committing changes to an svn repository using a git repository that doesn't have all the latest changes from svn.

Let's say I start an svn repository that contains two files, foo.txt and bar.txt. They only have a single revision so far. I do a git svn clone to start tracking the svn repository using git.

$ git log --oneline --decorate
7e72290 (git-svn, master) Initial commit.

You make changes to foo.txt and git commit them to your local master branch, so it moves ahead of git-svn.

$ git log --oneline --decorate
aa70eca (master) Added a line to foo.
7e72290 (git-svn) Initial commit.

What you didn't realize is that your friend already committed changes to bar.txtas svn revision 2.

Now when you run git svn dcommit from master, git will look for changesets between where you are and where git-svn left off. In this case, you only have one: aa70eca. git tries to send that diff to your svn repository.

$ git svn dcommit
Committing to [svn repo address] ...
        M       foo.txt
Committed r3
        M       bar.txt
r2 = 12b95b96e11f782f31b07a78756660cb82437ca2 (refs/remotes/git-svn)
        M       foo.txt
r3 = d4a7b84e0383f3af5fb0db439169c9f1b8af1152 (refs/remotes/git-svn)
W: aa70ecae4121854ac3754fb882a483b67d706a4a and refs/remotes/git-svn differ, using rebase:
:100644 100644 5771152459bfaa7cc62caa3b6b4d24e52ab8e447 dbfaecb10330d0509e092f1891a4a7e673802413 M      bar.txt
First, rewinding head to replay your work on top of it...
Nothing to do.

$ git log --oneline --decorate
d4a7b84 (git-svn, master) Added a line to foo.
12b95b9 Added to bar.
7e72290 Initial commit.

You can see that the commit succeeded as svn revision 3. When git-svn then sync'd your local svn history with the svn repository, it fetched all the new commits including the change you just submitted to svn. You'll notice that this change (d4a7b84) has a different SHA hash from the one you used to have in git (aa70eca). This is due to a variety of things: different commit timestamps, potentially different author names, the git-svn-id in the log of the commit fetched from svn, and different ancestry— the fetched svn r3 has r2 as its parent, but your git commit was descended from r1.

In this scenario, there was a diff found after fetching between the current git head (master) and SVN, since the content in r2 changed foo.txt. As a result, git-svn will rebase.

If I make a change and no other svn commits occurred in the meantime (or I had been running git svn rebase to keep up to date), then git-svn won't find a diff between the head and SVN, so it can just reset:

$ git svn dcommit
Committing to [svn repo address] ...
        M       foo.txt
Committed r4
        M       foo.txt
r4 = 533f7337999778628cf39fcd9155d085eb1c2b89 (refs/remotes/git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn
like image 126
Mike Seplowitz Avatar answered Oct 13 '22 22:10

Mike Seplowitz