21

My repo is SVN, and I do all development with git. We have a standard layout, and I initialized my local repo with git svn init -s <url to repo>

Here's my workflow for working with branches:

# creates a new branch remotely
git svn branch new-branch-name

# switches to a branch or trunk locally
git reset --hard name-of-branch
git reset --hard trunk

# merge changes from trunk into a branch
git reset —hard name-of-branch
git merge trunk
git svn dcommit

That last command above will commit the changes to the branch name-of-branch. My question is, how does git know this? When I do git reset --hard foo, what exactly happens?

This might just come down to a general question about git. Every time I try to research an answer I get confused about if svn integration is a special case or not.

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
John Bachir
  • 22,495
  • 29
  • 154
  • 227

3 Answers3

13

git-svn will look up the commit tree for ancestor commits that correspond to active SVN branches (the refs/remotes/... branches that correspond to branches in SVN). It will then dcommit to those.

Note that you should not merge and then dcommit -- SVN's and Git's branching model do not match up, and this kind of thing can fubar your SVN history. You should instead git rebase trunk when you are on the branch. (Alternatively, git svn rebase.)

Also, be aware that the branch you check out prior to the rebase should be a local branch. If it is not, you can create one with git checkout -b local-branch-to-create remote-branch. Then git rebase trunk.

If you want to squash all of the commits that were rebased into one, then do this after the rebase: git reset --soft trunk && git commit.

Once you are happy with the commits that now live on top of trunk, just git svn dcommit to push them to the SVN server.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • [1] "git-svn will look up the commit tree for ancestor commits that correspond to active SVN branches. It will then dcommit to those." -- Sometimes it guesses wrong -- is there a way for me to specify it explicitly? [2] "this kind of thing can fubar your SVN history" -- so, the history will be unideal, but the merging of the code files should be just fine, yes? – John Bachir Nov 12 '10 at 19:49
  • hmm, the man page says that `--commit-url` should be used only to switch transport, and "Using this option for any other purpose (don't ask) is very strongly discouraged." – John Bachir Nov 12 '10 at 19:51
  • If you want to specify a specific branch to commit to, just rebase your feature branch on top of the corresponding remote branch in your Git repo. – cdhowie Nov 12 '10 at 19:52
  • hmm. well first of all, `git rebase my-branch` and `git svn rebase my-branch` do not bring in the code from my-branch. `git merge my-branch` does have the desired changes locally, but then `git svn dcommit` tries to commit to my-branch remotely, instead of trunk. – John Bachir Nov 12 '10 at 20:02
  • 1
    That's because you're not using rebase right. `git checkout my-branch; git rebase trunk; git svn dcommit;` – cdhowie Nov 12 '10 at 20:03
  • Ah okay. So it's kosher to checkout the not-really-remote svn remote branch? When I do so it says "You are in 'detached HEAD' state." (see also [this question](http://stackoverflow.com/questions/4169017/why-does-git-remote-not-list-anything-on-my-git-svn-repo/4169308) ) – John Bachir Nov 15 '10 at 18:43
  • 1
    No, it's not... I'm taking `my-branch` to be a local topic branch where you've done your development, and `trunk` to be the name of the remote svn trunk ref. – cdhowie Nov 15 '10 at 18:45
  • Yeah, I just tried your three commands above, didn't work. it says "committing to trunk" (should say "my-branch"), and then it doesn't do anything (doesn't push up to server). have you done that pattern with git-svn, or just regular git branches? – John Bachir Nov 15 '10 at 18:46
  • 1
    I thought you were trying to merge your branch into trunk? Does my-branch correspond to a remote svn branch too? – cdhowie Nov 15 '10 at 19:31
  • yeah, i was. ah ha, i see -- I just tried making a local branch based off the remote branch, and then doing your recipe, and it worked! and it applies each changeset individually, therefor retaining history -- lovely! (is this process documented anywhere?) – John Bachir Nov 15 '10 at 22:59
  • It will apply each commit individually, yes, but it will also lose authorship information for each commit. If you want to apply the merge as one commit you could use something like: `git checkout my-branch; git rebase trunk; git reset --soft trunk; git commit; git dcommit;`. And this process is documented in pieces in the git-svn manpage. (You kind of have to put it together yourself from the various sections near the end of the manpage.) – cdhowie Nov 15 '10 at 23:03
  • I see. Wanna update your response to include all of this stuff? (do it for the kids.) (and then the process will be documented somehwere other than in pieces in the manpage :-) ) – John Bachir Nov 15 '10 at 23:53
  • 1
    Great answer. For more details, see the following page on the Git Wiki - https://git.wiki.kernel.org/index.php/GitTips#How_to_use_git_branches_with_git_svn – Matt Passell Mar 16 '11 at 22:08
  • 1
    @MattPassell : seems like the link is broken. The svn section is not longer in that wiki page. You can see when it happened: https://git.wiki.kernel.org/index.php?title=GitTips&diff=21551&oldid=21231 But the comment of that edit mention that part moved to https://git.wiki.kernel.org/index.php/GitSvnClient – jgomo3 Sep 04 '16 at 23:43
  • @jgomo3, agreed. Looks like I can't edit my comment at this point, so I guess people will have to read yours. :) – Matt Passell Sep 06 '16 at 13:29
2

Isn't it as simple as creating a local branch and tracking a remote svn branch? When you do a git svn init --stdlayout url-of-svn-repo, git brings down the whole svn repo, compresses it so that it is operable with git.

After that it is just a matter of fact of doing something like:

git checkout -b mybranch -t remotes/mybranch

If you have a local branch tracking a remote branch, git svn dcommit pushes only to the tracked remote branch.

  • 6
    I tried this and `git svn dcommit -n` still says that it will be committing to trunk instead of the branch I want – John Thompson Sep 30 '15 at 21:30
  • Is not that easy: "Git figures out what branch your dcommits go to by looking for the tip of any of your Subversion branches in your history – you should have only one, and it should be the last one with a git-svn-id in your current branch history." https://git-scm.com/book/en/v2/Git-and-Other-Systems-Git-as-a-Client#switching-active-branches-LPtGtkszIW – jgomo3 Sep 04 '16 at 23:39
1

Simple way if you'd like to dcommit git master into svn trunk, try the following commands:

git checkout master
git rebase trunk
git svn info # To verify that you're on the right branch
git svn dcommit

The same when on the other branch (e.g. 6.x)

git checkout 6.x
git rebase 6.x # or git rebase remotes/6.x
git svn info
git svn dcommit
kenorb
  • 155,785
  • 88
  • 678
  • 743