Mark Needham

Thoughts on Software Development

git: Only pushing some changes from local repository

with 4 comments

Something that we want to do reasonable frequently on my current project is to push some changes which have been committed to our local repository to master but not all of them.

For example we might end up with 3 changes we haven’t pushed:

>> ~/github/local$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 3 commits.
#
nothing to commit (working directory clean)
>> ~/github/local$ git hist
* bb7b139 Thu, 20 Oct 2011 07:37:11 +0100 | mark: one last time (HEAD, master) [Mark Needham]
* 1cef99a Thu, 20 Oct 2011 07:36:35 +0100 | mark:another new line [Mark Needham]
* 850e105 Thu, 20 Oct 2011 07:36:01 +0100 | mark: new line [Mark Needham]
* 2b25622 Thu, 20 Oct 2011 07:32:43 +0100 | mark: adding file for first time (origin/master) [Mark Needham]

And we only want to push the commit with hash 850e105 for example.

The approach which my colleague Uday showed us is to first take a temporary branch of the current state.

>> ~/github/local$ git checkout -b temp-branch
Switched to a new branch 'temp-branch'

Then immediately switch back to master and ‘get rid’ of the last two changes from there:

>> ~/github/local$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 3 commits.
>> ~/github/local$ git reset HEAD~2 --hard
HEAD is now at 850e105 mark: new line

We can then push just that change:

>> ~/github/local$ git push
Counting objects: 5, done.
Writing objects: 100% (3/3), 257 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /Users/mneedham/github/remote
   2b25622..850e105  master -> master

And merge the temporary branch back in again so we’re back where we were before:

>> ~/github/local$ git merge temp-branch
Updating 850e105..bb7b139
Fast-forward
 foo.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
>> ~/github/local$ git hist
* bb7b139 Thu, 20 Oct 2011 07:37:11 +0100 | mark: one last time (HEAD, temp-branch, master) [Mark Needham]
* 1cef99a Thu, 20 Oct 2011 07:36:35 +0100 | mark:another new line [Mark Needham]
* 850e105 Thu, 20 Oct 2011 07:36:01 +0100 | mark: new line (origin/master) [Mark Needham]
* 2b25622 Thu, 20 Oct 2011 07:32:43 +0100 | mark: adding file for first time [Mark Needham]
>> ~/github/local$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)

And finally we delete the temporary branch:

>> ~/github/local$ git branch -d temp-branch
Deleted branch temp-branch (was bb7b139).

We can achieve the same thing without creating the branch and just cherry picking the commits back again after we’ve pushed our changes but this seems approach seems quicker.

Be Sociable, Share!

Written by Mark Needham

October 20th, 2011 at 6:50 am

Posted in Version Control

Tagged with

  • If you think about it, it seems like git should have a built-in command to push only up to a certain commit to remote. Otherwise this is way too much hassle. It should be handled by the scm tool.

  • Another way would be to note the current revision, `git reset –hard last_commit_you_want_to_push`, push, and then `git reset –hard commit_you_noted_earlier`. If you forget the last commit, you can do a git reflog to see what the recent heads were.

  • Thanks Anthony! Didn’t realize you could reset –hard back to a later commit hash. Nice! Now if only git will include a new command that wraps these two steps 🙂

  • Viswesh Narayanan

    We can achieve the same thing by

    // Stashing changes
    > git reset HEAD~1
    > git stash save “last commit”
    > git reset HEAD~1
    > git stash save “last but one commit”

    // Now push the local commit you want the master to be
    > git push

    // Unstashing them
    > git stash pop
    > git commit “last but one commit”
    > git stash pop
    > git commit “last commit”