Moving changes on a Git branch

From Net-SNMP Wiki
Jump to: navigation, search

This page describes what to do if you are developing changes on a branch and need to move them to a different branch using Git

Scenario

Take the following example: I was working on some changes to the dist/makerelease.xml file and doing this on my local copy of the master branch. But in the end, these changes actually need to go into all of our active branches. Which means, if I'm going to follow our Git Workflow I need to first commit them to the lowest supported branch first. But... that's not where I committed them! Oh no!

[Never fear]

Starting Out

Here's a snapshot from gitk showing the tree where I started. Note that my master is ahead of the upstream origin/master. It is important you don't do anything on this page with changes that have been published! It's important. So I'll repeat it. In bold. It is important you don't do anything on this page with changes that have been published!

Error creating thumbnail: Unable to save thumbnail to destination

First we made a common mistake

We didn't do our changes in the right place (V5-4-patches) or, even better, in a new special branch for the new work (maybe "really-cool-new-release-script"). Ehh... Who cares. We can do this now by creating the new branch:

 # git checkout -b really-cool-new-release-script
 Switched to a new branch 'really-cool-new-release-script'

Results in:

Error creating thumbnail: Unable to save thumbnail to destination

Now we need to reset the master to get rid of all the changes to it (yeah, they'll just be merged in again later and this is silly, but...)

 # git checkout master  
 Switched to branch 'master'
 Your branch is ahead of 'origin/master' by 7 commits.
 
 # git reset --hard remotes/origin/master
 HEAD is now at 8e08fc5 Tweak RPM handling to work with library version 4.9

This results in removing all the changes from the master branch (--hard means 'don't even save them; discard them entirely):

Error creating thumbnail: Unable to save thumbnail to destination

Rebasing changes somewhere else

Now that we have the changes properly placed into a new branch, we can move the whole branch to rebase it (relocate it) somewhere else. Like where we want the branch to move to. We do this with git rebase and the --onto flag:

 # git checkout really-cool-new-release-script
 Switched to branch 'really-cool-new-release-script'
 
 # git rebase --onto V5-4-patches master really-cool-new-release-script
 First, rewinding head to replay your work on top of it...
 Applying: pull the branch info from git
 Applying: make the branch echo output and svn update converted to git equivalents
 Applying: remaining command line changes for svn -> git
 Applying: A script to invoke the correct version of the autoconf tool
 Applying: use the new run-autoconf script
 Applying: use git2cl to generate the ChangeLog file; needs much more work.
 Applying: xml fixes

Which actually moves all the changes (one at a time) to the V5-4-patches tree (it would have stopped us in the middle if it failed because of a conflict, but it didn't):

Error creating thumbnail: Unable to save thumbnail to destination

Now we can "properly" apply them

Now that they're hanging off the right branch, we can apply them directly to the branch:

 # git checkout V5-4-patches
 Switched to branch 'V5-4-patches'
 
 # 'git merge --ff really-cool-new-release-script
 Updating af8b235..df9cf9a
 Fast-forward
  dist/makerelease.xml |   76 +++++++++++++++++++++++--------------------------
  dist/run-autoconf    |   32 +++++++++++++++++++++
  2 files changed, 68 insertions(+), 40 deletions(-)
  create mode 100755 dist/run-autoconf
Error creating thumbnail: Unable to save thumbnail to destination

Deleting the unused branch

 # git branch -d really-cool-new-release-script
 Deleted branch really-cool-new-release-script (was df9cf9a).

Rolling Upward

Now that we have the changes applied on the right branch, we can apply them to all the active branches using the nsrollup shell macro:

 # nsrollup
 [Long merging output deleted]]

Resulting in:

Error creating thumbnail: Unable to save thumbnail to destination

And Pushing the Whole Mess Forward

 # 'git push --all
 Counting objects: 50, done.
 Delta compression using up to 2 threads.
 Compressing objects: 100% (39/39), done.
 Writing objects: 100% (39/39), 5.22 KiB, done.
 Total 39 (delta 29), reused 0 (delta 0)
 To ssh://hardaker@net-snmp.git.sourceforge.net/gitroot/net-snmp/net-snmp
    af8b235..df9cf9a  V5-4-patches -> V5-4-patches
    d588ec8..d39194b  V5-5-patches -> V5-5-patches
    127eec2..64b6c68  V5-6-patches -> V5-6-patches
    8e08fc5..a308656  master -> master
Error creating thumbnail: Unable to save thumbnail to destination

But but but...

You made that too complex! You didn't actually need to create a new branch!!! You cheater!'

Yeah, I did. But you learned more this way, like how to move changes to a branch, etc. And it's conceptually a bit easier than dealing with change sets.

And what's with the moving them and then just reapplying them later?

Well, technically it wasn't necessary. But it showed good practice by applying them where they should go and then merging upward. Either way, the resulting files were the same. You're right.

Exercises left to the reader

  1. Do the above without creating a new branch
  2. Do the above, but with only a subset of the changes, in the middle of course (hint: git cherry-pick)