0

I have a number of commits on a file:

  • commit E
  • commit D
  • commit C
  • commit B
  • commit A

I believe I introduced an error in commit C. I want to remove all of the changes introduced in Commit C on that one file, without affecting the other changes, and so it looks like A -> B -> D -> E.

Musical Shore
  • 1,243
  • 2
  • 19
  • 35
  • see the docs for git revert – Andreas Dec 04 '15 at 19:07
  • One possibility: you can use the `--no-commit` flag to `git revert` and reset the changes to all other files – Whymarrh Dec 04 '15 at 19:11
  • You can't remove commit C without removing all of the changes in that commit. Where do you want the changes to the other files that changed in commit C to be stored? – Ajedi32 Dec 04 '15 at 19:27
  • Possible duplicate of [Delete commits from a branch in Git](http://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git) – Andrew C Dec 04 '15 at 22:49
  • Possible duplicate of [Remove sensitive files and their commits from Git history](http://stackoverflow.com/questions/872565/remove-sensitive-files-and-their-commits-from-git-history) – Vogel612 Dec 07 '15 at 08:39

3 Answers3

2

You can try this:

  1. Check out a separate branch for your current working state (e.g., backup_branch).
  2. Find out the commit hashes of commits B, D and E (e.g., do a git log).
  3. On your target (not backup) branch, revert to commit B by doing git reset --HARD committish_b, where committish_b is whatever you found for the commit hash of commit B. By doing this, you will lose all the changes you made after commit B on your target branch.
  4. Cherry pick commits D and E onto your target branch by doing git cherry-pick committish_d and git cherry-pick committish_e.
LateCoder
  • 1,773
  • 1
  • 20
  • 38
1

Each commit comes with a hash.

Let's say the hash of commit C was abc123

you could do a simple git revert <hash>

$ git revert abc123

The git revert command undoes a committed snapshot. But, instead of removing the commit from the project history, it figures out how to undo the changes introduced by the commit and appends a new commit with the resulting content. This prevents Git from losing history, which is important for the integrity of your revision history and for reliable collaboration.

source

Edit:

According to your comment, you wanted to just revert a file rather than the entire commit. If this is the case, then consider the following:

commit B has a hash of abc456.

$ git checkout abc456 -- /path/to/file.ext
ddavison
  • 25,442
  • 12
  • 70
  • 96
  • I only want to revert one file, not the entire commit. – Musical Shore Dec 04 '15 at 19:09
  • oh, that's not what this question said. i will edit my answer. – ddavison Dec 04 '15 at 19:10
  • Will this not revert back to Commit B? I want to undo the changes introduced by Commit C, as if Commit D were checked in next after Commit B, and I only want it to affect one file. – Musical Shore Dec 04 '15 at 19:12
  • 1
    no it wont - that's why i included the docs above (the quoted material). If you did a revert, it will result in commit E being the latest, but without the committed content in C – ddavison Dec 04 '15 at 19:12
  • Ok, but how do I do that for a specific file? In your example, for a specific file you use `git checkout`. – Musical Shore Dec 04 '15 at 19:15
  • 1
    exactly what i show in the edit. find commit B's hash of the file, then use `git checkout -- /the/file`. This will check out commit B's version of the file. – ddavison Dec 04 '15 at 19:17
  • I don't want commit B, I want Commit E without the changes introduced in Commit C. – Musical Shore Dec 04 '15 at 19:21
0

git checkout commitE-SHA

git checkout commitB-SHA /path/to/file

(then commit as usual)

This will create a new commit to undo the changes in the one file.

This is better (safer, easier, less confusing) than trying to rewrite history or remove the errant commit or errant file from the history.

Brad Thomas
  • 3,970
  • 6
  • 30
  • 53