MarcoS
MarcoS

Reputation: 17721

Revert to last stable commit without losing newer commits

I'm quite new to git, so I ask before making any unrecoverable mistake... :-)
In the last days I made some changes to my project to upgrade to new versions of some libs I use, but I failed (also for shortage of libs docs... :-().

I did just resolve to abandon the upgrade, so now I need to revert to last stable commit.
I did also push to remote, but this shouldn't be a problem since I am currently the only dev on this project.

This is my current git log:

$ git log --oneline
22c0713 Upgrading to Firebase 1.1
6d5f9f4 Porting customers to angularfire 0.8
fd9db42 Porting to Angularfire 0.8
d728b82 Working out authenticating on authenticated session problems
d511245 Testing authWithOAuthRedirect
abd9849 Porting to firebase 1.1.2
8884b88 Testing loadRemote() with relative path on public repositories
7830eea Testing loadRemote() with relative path on public repositories
f36c2f5 Finished working on I18N
...

f36c2f5 commit (the last one I show above) is the last stable one, the one I'd like to revert to.

I would also like to avoid loosing newer (bad) commits, for possible future reference.

Which is the most advisable strategy for this task?

UPDATE: I'm almost there, thanks to your answers (going to accept in a minute...). Just one more little issue: I have also a "gh-pages" branch, to push my dist subfolder to github gh-pages staging site.
Now, after

git checkout -b my_branch_for_future_reference
git checkout master
git reset --hard f36c2f5
git push -f

doing

git subtree push --prefix dist origin gh-pages

I get this error:

git push using:  origin gh-pages
To [email protected]:MYUSER/MYREPO.git
 ! [rejected]        3febf7c0812441c7379710d0a1f5f1ec26adbd9e -> gh-pages (non-fast-forward)
error: failed to push some refs to '[email protected]:MYUSER/MYREPO.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

I checked, but git subtree push has no '-f' flag... :-(

UPDATE 2: I think I found an answer to my last question myself:

git push origin `git subtree split --prefix dist master`:gh-pages --force

could be the solution, right? (I did not run it yet... :-).

UPDATE 3: yes, that is the solution to force push of subtree.

Upvotes: 5

Views: 2273

Answers (5)

dan
dan

Reputation: 13272

Assuming that you are now on master branch, you can create a new branch named experiment and then revert the master to f36c2f5. Eg.

Ensure that you don't have uncommitted data, then create the new experiment branch

git branch experiment 

Reset master to the last good commit:

git reset --hard f36c2f5

Upvotes: 0

Rich
Rich

Reputation: 7795

There's several different ways you could go about this. You could simply use a series of git revert commands to create new commits that undo the changes in the commits you no longer want.

git revert 22c0713
git revert 6d5f9f4
...
git revert 7830eea

(Note that the git revert command can take multiple commits, so you could do this in a single command, but I've personally had mixed results with that.)

Alternatively, you could create a new branch at the current HEAD:

git branch for_future_reference

And then reset your current (pre-existing) branch to point to the commit you want:

git reset --hard f36c2f5

Note that with the latter method you will need to "force" the push (git push -f) to remote in order to rewrite the history. As such, the former method might be preferable, even as a solo developer.

Upvotes: 0

pattivacek
pattivacek

Reputation: 5823

My usual strategy in this situation is to make a new branch (git branch <new_branch_name>) and then reset your current branch to the commit you've specified (git reset --hard <commit>, in this case git reset --hard f36c2f5). Be careful with git reset --hard, though, as it will blow away any uncommitted changes in your working tree.

Your current branch will be back at the stable commit, but your other commits are still readily accessible in your newly created branch.

Upvotes: 1

Tom De Leu
Tom De Leu

Reputation: 8274

I would do it like this:

git checkout -b upgrades
git checkout master
git reset --hard f36c2f5
git push -f

Explanation:

  • keep the latest (bad) commits by keeping them in a separate branch, for later
  • checkout master
  • reset master to the commit you mentioned: this throws away later commits on the master (but the "upgrades" branch will still have them)
  • push master, with the "-f" = "force" flag as you want to overwrite the remote to throw away some commits (without "-f", git will not allow you to do this)

Upvotes: 2

sschuberth
sschuberth

Reputation: 29867

One possibility is to create a local branch pointing to the most recent "bad" commit

git branch most-recent-bad-commit

and then making your current branch point to the last "stable" commit

git reset --hard f36c2f5

Note that the latter will also delete any uncommitted changes to tracked files. Untracked files will not be modified.

Upvotes: 0

Related Questions