4

I started working on a bunch of new features in the code without branching.

Those new features are not ready to deploy. However, an urgent request has come in to fix a different issue.

I'd like to go back to the version before I started adding the new features, apply the fix there, and then deploy.

However, I'm confused as to which one should become a branch, and which version should merge to which.

Can someone provide me with a solution to this problem, as a step by step git process to get this done.

Note, I've never branched on source control (now I see why I should have)!

andy
  • 8,775
  • 13
  • 77
  • 122

4 Answers4

2

This is one way, there might be an easier one. This also assumes that the changes you made are only local on your machine and not pushed to any remote branches.

Lets say we have

           master
             |
A - B - C' - D'

where C' and D' mark commits with the new features, which you don't want to deploy.

First, create a new branch at the current commit (master):

git branch new_feature

Now we have to pointers to the commit D', master and new_feature. This is important to not loose any of the changes you already did.

           master
             |
A - B - C' - D'
             |
        new_feature

Now we want to reset the master branch to a state without new features, i.e. to commit B We can do that using git reset --hard.
Important: If you have uncommitted changes at this point, they will be lost. I recommend to read this excellent article about git reset, to understand what it is really doing.

git reset --hard B

The structure will now look like:

   master
    |
A - B - C' - D'
             |
        new_feature

On the master branch, you can now make your hotfix changes (commit E) and push them to heroku:

      master
        |
A - B - E
     \
      C' - D'
           |
       new_feature

Then you can either merge the hotfix into the new_feature branch, or just rebase it on top of the hotfix:

git rebase master new_feature

which results in:

      master
        |
A - B - E
         \
          C' - D'
               |
          new_feature

The Pro Git book is a really good source to learn Git, and it's free: http://git-scm.com/book.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    @andy: Yes, then you should *not* do a simple `git reset`. Mmmh. In that case, doing a `git revert` might be the better option, like Tres mentioned. – Felix Kling Mar 24 '13 at 22:37
  • good man, thank you. Also I called you felox, not felix, please forgive me. – andy Mar 24 '13 at 23:10
  • thanks again for you answer felix, the time and explanation is really appreciated. Since I'm going with a revert I'm going to mark trey's as the answer, but your contribution is much appreciated. – andy Mar 24 '13 at 23:13
  • It's all fine, always happy to help :) I really recommend reading the book I linked to (online). It is well written, and personally, I really enjoyed reading it. Happy coding and good luck with you project! – Felix Kling Mar 24 '13 at 23:26
1

What I would do is create a branch from your current state as a feature branch so you don't lose any work.

git checkout -b new-features && git push origin new-features

Now that you've saved your current state to a branch (and pushed it to the remote), git checkout your original branch and revert it back to a point before your current head.

The best way to do this is to use git revert. A good explanation on why and how can be found on: Revert multiple git commits.

Once you reverted the changes, committed, and pushed, I'd recommend you create a branch to develop the bugfix on. This is good practice for the same reason people create feature branches. A good rule of thumb is to create a branch with the same or similar name / number as the issue you are working on. Do all of your changes on there and when it's all done, you can pull it in to whatever branch you are tagging your deployments from.

The best part about this is that it works whether or not any changes have been pushed to a remote, is simple and follows best practices.

Hope that helps.

EDIT: To answer question in comment.

"This also assumes that the changes you made are only local on your machine and not pushed to any remote branches."

That method will not work if you've already pushed. There are ways around it, but I wouldn't recommend it.

Basically, the only difference between the two methods at their core is that one does git reset --hard [commit] and the other uses git revert. Resetting actually tells git to go back to a particular commit, which is essentially the effect you want, but is frowned upon if you've already pushed. Since git will not allow a push to have non-fastforwarding changes and you have actually erased history, you'd have to do a git push origin [branch] --force causing the remote to also lose the changes.

Revert actually creates a commit that adds history to git about the commits you are undoing. This is better because all reverted changes can be tracked and anyone who has pulled from that branch will not become out of sync. They will get the revert, or reverts, when they pull. A good side effect of this is that if you make a mistake in your reverted change, you can revert it later since it is just another commit.

Community
  • 1
  • 1
Tres
  • 5,604
  • 3
  • 19
  • 17
0

you can create a new branch now, like git checkout -b my_current_work, then you can go back to master - git checkout master, and go back to the commit which was deployed [ I hope you remember ]. You can use for example gitk command to see the graph and get the hash of the proper commit. After that you can either git checkout hash_of_the_commit or git reset --hard hash_of_the_commit ( I would recommend checkout, it is safer I believe ). If it was the previous commit, you can always use syntax like git checkout HEAD~1, where ~1 means previous commit, ~2 would mean second last commit etc. Your whole work should be still in the "my_current_work" branch, so you will not lose anything. Just make sure you commit all your changes before creating new branch.

mkk
  • 7,583
  • 7
  • 46
  • 62
0

I started working on a bunch of new features in the code without branching.

Assuming you haven't committed any of them, you could commit them on a temporary branch.

git checkout -b temp_work
git commit -am "temporary work"

Then you could checkout master again, branch from there and do your urgent work there.

git checkout -b urgent_work

When you're done with, passes its tests etc, then merge it back to master

git checkout master
git merge urgent_work
alex
  • 479,566
  • 201
  • 878
  • 984