4

I've made a series of commits in my branch. However, the last 3 or so were mistakes - I want to 'revert' my branch to a previous commit.

Googling the issue I understand I must use git log to get the ID of the commit I want to return to, then git checkout <id>. But I cannot find information beyond that.

It seems when I checkout I am no longer within my original branch. How do I merge back into my original branch, thus undoing the changes in the previous erroneous commits?

MeltingDog
  • 14,310
  • 43
  • 165
  • 295
  • 2
    Possible duplicate of [How to undo the most recent commits in Git?](https://stackoverflow.com/questions/927358/how-to-undo-the-most-recent-commits-in-git) – phd Jun 04 '18 at 04:06
  • 1
    No need to checkout — use `git reset` or `git revert`. No need to lookup commits IDs — use [revision paths](https://git-scm.com/docs/gitrevisions) like `HEAD~2`. To return back to a branch from detached HEAD run `git checkout $branch`, e.g. `git checkout master`. – phd Jun 04 '18 at 04:08
  • @phd: I thought `revert` is the save way? I always wonder why people always suggest `reset` first. – Christoph Jun 04 '18 at 14:38
  • @Christoph `revert` creates excessive commits, history editing with `amend/rebase/reset` allow to have clean history. Of course you have to understand what you're doing with all advantages and disadvantages. – phd Jun 04 '18 at 14:41

4 Answers4

0

If you simply want to add a new commit that restores the file states,

First, remove all files using rm (be careful not to remove .git/). You can also use git rm -f, but pay attention to .gitignore changes.

Then, fetch all files from a commit (get the commit SHA using git log):

git checkout 1234567 \*

Here the asterisk is escaped to prevent shell expansion. Git will do the expansion. If you're using a Unix shell, you can also use single quotes:

git checkout 1234567 '*'

Commit the fetched files:

git add -A
git commit

Voilà!

iBug
  • 35,554
  • 7
  • 89
  • 134
0

when your you create a branch from another are created two lines works which could take lines different then in the branch current can not view the commits other branches, as are independent, but if you're done your work in that branch suppose is called "dev" then if you want to run the your main branch (master) only you should confirm your stagin area marge your branches something like this: firts verify your current branch with git branch it show the Name of current HEAD Them go to master git checkout master and finally marge branches git marge dev (dev = name_of_your_branch) and you can show all logs of two branches with git log --graph

juancarlos
  • 593
  • 3
  • 9
0

The most foolproof way I have found is simply to clone the repository again so that you have a second copy of the repository in another folder. Let's say you have done that and have folders MyRepo and MyRepo2, both of which point to the latest version in the desired branch of the repository.

Now check out the specific good commit in MyRepo2, then use a file compare tool to see what files have changed between MyRepo and MyRepo2. You can then copy the changed files from MyRepo2 to MyRepo, check in and push.

The above can be done in one line as outlined in this excellent answer to a similar question.

git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply
mcarans
  • 1,275
  • 9
  • 16
-1

If you want to completely remove the last to commit and the working directory to coincide with last but two commit (HEAD~~):

git reset --hard HEAD~~

But if you don't want to modify commit history (because you want to keep wrong commits or you already have pushed it to common repository), just revert to earlier state but keep wrong commits, then iBug's method with checkout is better. The problem with your solution is that 'git checkout doesn't move the branch pointer only the head pointer so get to a detached head state. If you check out individual files and not commits then your pointers remains at their original place, so you don't need to merge afterwards. (some explanation for my code: the above command moves not just the HEAD pointer, but the master branch pointer two step back to HEAD~~, and updates the working directory (and index) to coincide with commit HEAD~~

HEAD : current commit HEAD~ : previous commit HEAD~~ HEAD~~~..etc)

badicst
  • 1
  • 3