git-svn dcommiting a single git commit

前端 未结 4 575
感动是毒
感动是毒 2021-01-31 04:01

Given multiple unpushed git commits, is it possible to git-svn dcommit only one of those commits?

e.g. I have commit foo, bar, and baz, but rig

相关标签:
4条回答
  • 2021-01-31 04:37

    (The following assumes your work is on master.)

    First, reorder your last three commits so that bar is first.

    git rebase -i HEAD~3
    

    An editor will pop up with something like this:

    pick 498e4f4 foo
    pick 71547ae bar
    pick abf09c6 baz
    
    # Rebase 4d3fe72..abf09c6 onto 4d3fe72
    #
    # ...
    

    Reorder them in the editor that pops up so that bar comes first.

    pick 71547ae bar
    pick 498e4f4 foo
    pick abf09c6 baz
    
    # Rebase 4d3fe72..abf09c6 onto 4d3fe72
    #
    # ...
    

    Git will spin for a few seconds and burp up a confirmation:

    Successfully rebased and updated refs/heads/master.
    

    Now you can temporarily roll back to the bar commit (HEAD~2 means two commits back from HEAD) and dcommit it:

    git checkout HEAD~2
    git svn dcommit
    

    If you're paranoid like me, you can do git svn dcommit -n first to be sure you're only committing what you want.

    Now jump back to master:

    git checkout master
    

    The last bit is to rebase so that master syncs up with svn:

    git svn rebase
    

    It's a little fuzzy to me why this is required, but I'm guessing that dcommitting in a detached HEAD state has something to do with it.

    0 讨论(0)
  • 2021-01-31 04:40

    git svn dcommit cannot selectively commit bar. if you have directly committed foo, bar and baz on your master branch then you have to do the following to get only bar in svn.

    Assume bar's commit sha is something like 13abc...

    and git log master shows all your 3 commits foo, bar and baz.

    • you need to create a branch from master

      git branch wip

    the wip branch now has foo, bar and baz

    • reset the master's head to a commit before any of foo, bar or baz. you can do that using git reset (read the manual, the differences between hard,soft and mixed options affects uncommitted changes in your working tree)

      git reset --hard (COMMIT-ID before foo,bar,baz)

      (or)

      git reset --hard HEAD~3 (go back 3 revisions)

    now your master branch has none of foo, bar or baz. verify with git log.

    • now you can cherry pick only the commits you want to dcommit to svn from the wip branch into master. so to get bar

      git cherry-pick wip 13abc (sha of bar commit)

    the master only gets the bar commit alone.

    • now git svn dcommit should push bar alone.

    Suggested Future usage

    So for git-svn it is preferable not to make commits directly on master branch which is tracking remote svn. do your work on local branches and merge selectively to master before dcommiting.

    0 讨论(0)
  • 2021-01-31 04:49

    I have one sort of crusty answer. You can create a new branch with out foo, bar, and baz in it and then cherry-pick bar to the new branch and then git-svn dcommit that branch and remove it when you're done. That doesn't seem very elegant though.

    So assuming foo, bar, and baz are in branch x and master doesn't have any of them.

    git branch y master

    git checkout y

    git cherry-pick <sha1 of bar>

    git svn dcommit

    git checkout x

    git svn rebase

    git branch -d y

    If master does have these commits you can reset the head as Sizzler suggests.

    0 讨论(0)
  • 2021-01-31 04:49

    I somtimes only want to commit a few commits of my branch. E.g.

    A-----B-----C------D  
    ^                  ^
    |                  |
    svn/trunk          trunk
    

    If I want to commit B and C but not D I create a new branch, do a svn dcommit, switch back to trunk and delete the branch.

    While I'm on branch trunk I do

    git checkout -b temp `C`
    git svn info // just to check that branch temp is properly connected to svn
    git svn dcommit
    git checkout trunk
    git branch -D temp
    

    EDIT

    Like Stefan commented:

    With an additional 'git svn rebase' it worked well for me.

    This is necessary, because the commits that are committed to svn will be rewritten. git-svn adds the git-svn-id to the commit message and therefore the commit hash changes even if the commit's contents are the same. But since the contents are the same the rebase will not cause conflicts.

    PS: I also often omit the new branch and just checkout detached. E.g.

    git checkout --detach C
    git svn dcommit
    git checkout trunk
    git svn rebase 
    
    0 讨论(0)
提交回复
热议问题