Search code examples
gitrevertchangeset

How to revert a commit and put changes back to stage


How can I revert a commit but put the changes but on the stage so I can edit the commit until it is what I want.

Formerly I've been familar with TFS, where revert did exactly that, but in GIT git revert seem to automatically check-in the undone commit, so no chance to keep something from the changeset.


Solution

  • You can use git revert -n. I would advise that you don't. Make a separate commit to make the changes that you do want.

    The reason for that is simple enough. A commit is a snapshot, but it represents a change. To find the change from the snapshot, Git compares the commit to its immediate parent.

    That is, if file A had 10 lines before, and has 11 now, comparing the old copy of file A to the new copy of file A will (probably) show that someone added one line. The diff will say: to change the old commit to the new one, add this one line to file A. If file B had 20 lines before, and has 19 now, the diff will say: to change the old commit to the new one, delete this one line from file B.

    A simple git revert that commits will, when shown, show the same change but backwards: delete this one line from file A, and add this one line to file B.

    If what you meant—and will commit in this third commit—is to just add the one line to file A, now you have a correct single commit which, when shown, will say add this one line to file A.

    If you instead make a non-committing revert, then put the line back, you'll have to add together two separate commits—the mistaken one, and the correcting revert—to see what was actually intended. That's not wrong, but it means that anyone coming along later, to see what happened and what they might need to do in some similar situation, has to work harder.

    Compare these instructions:

    1. "Do X; wait, no, don't do X. Do Y."
    2. "Do X. Then while undoing X, do Z."

    Which would future-you prefer to see?

    (Note that you can construct commit Y by doing:

    git cherry-pick -n X
    

    where X is the one that you reverted. That way, you get all the changes, but can start undoing them.

    Note also that git revert -n and git cherry-pick -n put everything into the staging area—that is, they do a git add on all the updated files. There's no actual problem with that, but if you don't like it, you can run git reset to un-stage.)