Git equivalent of Mercurial phases?

739 Views Asked by At

In mercurial, I regularly use secret changesets to track my work on stuff that isn't quite ready to push yet. Then, if I need to make an emergency change to some file, I can update to the public revision, make that change and push it, without having to worry about my unfinished changesets getting pushed.

IE:

hg commit -sm "Partial work"
# Crap, prod is down
hg up -r <public version number>
hg commit -m "Fixin prod"
hg out
  1 outgoing change, "Fixin prod"
hg push
hg rebase -r <secret revisions> -d.
# later
hg commit --amend -m "Finished work"
hg phase -dr.
hg out
  1 outgoing change, "Finished work"
hg push 

How would you do this in git?

2

There are 2 best solutions below

0
On

Using branches:

$ git checkout -b dev #create a new branch based on the current commit in master
# .... work ....
$ git commit -a -m 'super awesome new feature'
# oh noes, production crapped itself!
$ git checkout master
# ... fix ...
$ git commit -a -m 'fixed bug #666'
$ git push master
$ git checkout dev #since we created the branch with -b the first time, we're good now.
$ git merge master # update our dev branch with the changes in master
# ... work on new features ...
# all done and commited and tested
$ git checkout master
$ git merge dev && git branch -d dev # delete the dev branch
$ git push && profit

Or simply use git stash:

# ... work on new feature ...
# oh noes, production caught a killer virus from aliens
$ git stash
# ... fix and commit and push ...
$ git stash apply # reapply your stashed code
# resume hacking on your new feature.

I personally prefer the branches method since it's cleaner.

0
On

How would you do this in git?

I never use the default behavior of "git push". To enforce it, it's possible to set push.default to "nothing". Then there are 2 ways to push:

  1. Set remote.<name>.push. For my github stuff I usually have this in my .git/config:

    [remote "origin"]
    ...
     push = refs/heads/export/*:refs/heads/*
    

So if I decide that some commit is ready for pushing I put there branch "export/<feature>". Until I do it, the commit won't be pushed by "git push".

  1. or just always explicitly specify which branch you are pushing to in commandline. Like this:

    $git push origin 3f42873:refs/heads/12345_foo
    

This is what I do at work, where branches always come and go, and I don't want to track each of them. It leaves some chance for mistake though, so if you want to be sure use the first option.

The refspec syntax is described here: https://www.kernel.org/pub/software/scm/git/docs/git-push.html