Search code examples
gitgit-svn

git svn rebase while others work on my files


I am new to git and I am trying to work with it against my SVN server. I don't understand the reason to "git svn rebase" to get updated. From what I understand, if I update my local repository with the SVN server, commit to GIT (locally) my changes, and than "git svn rebase", I might overwrite other users changes on the files I work on.

Do I understand correctly? and if I do, why would I want to use rebase and take such risk (I understand the idea of fast forward, but it sounds really risky)?

Hope I am not missing something basic!


Solution

  • The opposite is true: git svn rebase prevents you from overwriting others' work. As the Git-SCM book aptly notes, think of git svn rebase as your equivalent of svn update. It is the way you update your local repository with the SVN server.

    In a standard SVN workflow...

    ...you check out a repository version (let's say, @9001). You make some changes, and are ready to commit, but—oops—someone checked in change 9002. You svn update to revision 9002, merge if necessary, and then check in your change to produce 9003. If you hadn't run svn update, you would overwrite your teammate's revision 9002; by running svn update you're acting as though you based your work on revision 9002 and not 9001.

    SVN         9001-------------------------------9002---------------9003--------->
                    \                                  \             / svn commit
    your feature     local work       [now update]      updated work
    

    In a standard git workflow...

    ...history isn't numbered and linear. You can commit whenever you want, locally, and merge your work into whichever commit your team designates the "master" branch.

    your teammate's feature            T1--T2--T3---T4--T5
                                      /                   \  merge
    master      M1------------------M2-------M3------------M4--------M5------------->
                                               \                    / merge
    your feature                                Y1-----Y2-----Y3--Y4
    

    I've labeled Y1 Y2 Y3 Y4 as your local commits of your feature work, all based on the state of the world you checked out M3. All of this history is public, so if you were to commit just like the above, your teammates could tell you based Y1 off of M3. If you wanted to change that, you could ask git to base your feature work off of M4 instead. That's known as a git rebase.

    your teammate's feature            T1--T2--T3---T4--T5
                                      /                   \  merge
    master      M1------------------M2-------M3------------M4----------------M5----->
                                                             \              / merge
    your feature after rebase                                 Y1--Y2--Y3--Y4
    

    After the rebase, all of the commit IDs (hashes) change, because they're computed based on the parents of your commit and by rebasing you deliberately change the parents.

    So in your git+svn workflow...

    ...you need to map git's commit graph onto svn's linear history. This means running an svn update (git svn rebase) before you commit in order to base your work off of the latest revision in the SVN repository.

    SVN         9001-------------------------------9002----------------9003--------->
                    \                                  \              / git svn dcommit
    your feature     Y1--Y2--Y3--Y4   [now rebase]      Y1--Y2--Y3--Y4
    

    See the Git-SCM chapter on SVN for more explanation and examples.