diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 645f0c1748..b04d129b3f 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -8,40 +8,50 @@ git-reset - Reset current HEAD to the specified state SYNOPSIS -------- [verse] -'git reset' [--mixed | --soft | --hard | --merge | --keep] [-q] [] 'git reset' [-q] [] [--] ... 'git reset' --patch [] [--] [...] +'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [] DESCRIPTION ----------- -Sets the current head to the specified commit and optionally resets the -index and working tree to match. +In the first and second form, copy entries from to the index. +In the third form, set the current branch to , optionally +modifying index and worktree to match. The defaults to HEAD +in all forms. -This command is useful if you notice some small error in a recent -commit (or set of commits) and want to redo that part without showing -the undo in the history. +'git reset' [-q] [] [--] ...:: + This form resets the index entries for all to their + state at the . (It does not affect the worktree, nor + the current branch.) ++ +This means that `git reset ` is the opposite of `git add +`. -If you want to undo a commit other than the latest on a branch, -linkgit:git-revert[1] is your friend. - -The second and third forms with 'paths' and/or --patch are used to -revert selected paths in the index from a given commit, without moving -HEAD. - - -OPTIONS -------- ---mixed:: - Resets the index but not the working tree (i.e., the changed files - are preserved but not marked for commit) and reports what has not - been updated. This is the default action. +'git reset' --patch|-p [] [--] [...]:: + Interactively select hunks in the difference between the index + and (defaults to HEAD). The chosen hunks are applied + in reverse to the index. ++ +This means that `git reset -p` is the opposite of `git add -p` (see +linkgit:git-add[1]). +'git reset' [--] []:: + This form points the current branch to and then + updates index and working tree according to , which must + be one of the following: ++ +-- --soft:: Does not touch the index file nor the working tree at all, but requires them to be in a good order. This leaves all your changed files "Changes to be committed", as 'git status' would put it. +--mixed:: + Resets the index but not the working tree (i.e., the changed files + are preserved but not marked for commit) and reports what has not + been updated. This is the default action. + --hard:: Matches the working tree and index to that of the tree being switched to. Any changes to tracked files in the working tree @@ -59,179 +69,23 @@ OPTIONS the given commit. If a file that is different between the current commit and the given commit has local changes, reset is aborted. +-- --p:: ---patch:: - Interactively select hunks in the difference between the index - and (defaults to HEAD). The chosen hunks are applied - in reverse to the index. -+ -This means that `git reset -p` is the opposite of `git add -p` (see -linkgit:git-add[1]). +If you want to undo a commit other than the latest on a branch, +linkgit:git-revert[1] is your friend. + + +OPTIONS +------- -q:: --quiet:: Be quiet, only report errors. -:: - Commit to make the current HEAD. If not given defaults to HEAD. -DISCUSSION ----------- - -The tables below show what happens when running: - ----------- -git reset --option target ----------- - -to reset the HEAD to another commit (`target`) with the different -reset options depending on the state of the files. - -In these tables, A, B, C and D are some different states of a -file. For example, the first line of the first table means that if a -file is in state A in the working tree, in state B in the index, in -state C in HEAD and in state D in the target, then "git reset --soft -target" will put the file in state A in the working tree, in state B -in the index and in state D in HEAD. - - working index HEAD target working index HEAD - ---------------------------------------------------- - A B C D --soft A B D - --mixed A D D - --hard D D D - --merge (disallowed) - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - A B C C --soft A B C - --mixed A C C - --hard C C C - --merge (disallowed) - --keep A C C - - working index HEAD target working index HEAD - ---------------------------------------------------- - B B C D --soft B B D - --mixed B D D - --hard D D D - --merge D D D - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - B B C C --soft B B C - --mixed B C C - --hard C C C - --merge C C C - --keep B C C - - working index HEAD target working index HEAD - ---------------------------------------------------- - B C C D --soft B C D - --mixed B D D - --hard D D D - --merge (disallowed) - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - B C C C --soft B C C - --mixed B C C - --hard C C C - --merge B C C - --keep B C C - -"reset --merge" is meant to be used when resetting out of a conflicted -merge. Any mergy operation guarantees that the work tree file that is -involved in the merge does not have local change wrt the index before -it starts, and that it writes the result out to the work tree. So if -we see some difference between the index and the target and also -between the index and the work tree, then it means that we are not -resetting out from a state that a mergy operation left after failing -with a conflict. That is why we disallow --merge option in this case. - -"reset --keep" is meant to be used when removing some of the last -commits in the current branch while keeping changes in the working -tree. If there could be conflicts between the changes in the commit we -want to remove and the changes in the working tree we want to keep, -the reset is disallowed. That's why it is disallowed if there are both -changes between the working tree and HEAD, and between HEAD and the -target. To be safe, it is also disallowed when there are unmerged -entries. - -The following tables show what happens when there are unmerged -entries: - - working index HEAD target working index HEAD - ---------------------------------------------------- - X U A B --soft (disallowed) - --mixed X B B - --hard B B B - --merge B B B - --keep (disallowed) - - working index HEAD target working index HEAD - ---------------------------------------------------- - X U A A --soft (disallowed) - --mixed X A A - --hard A A A - --merge A A A - --keep (disallowed) - -X means any state and U means an unmerged index. - -Examples +EXAMPLES -------- -Undo a commit and redo:: -+ ------------- -$ git commit ... -$ git reset --soft HEAD^ <1> -$ edit <2> -$ git commit -a -c ORIG_HEAD <3> ------------- -+ -<1> This is most often done when you remembered what you -just committed is incomplete, or you misspelled your commit -message, or both. Leaves working tree as it was before "reset". -<2> Make corrections to working tree files. -<3> "reset" copies the old head to .git/ORIG_HEAD; redo the -commit by starting with its log message. If you do not need to -edit the message further, you can give -C option instead. -+ -See also the --amend option to linkgit:git-commit[1]. - -Undo commits permanently:: -+ ------------- -$ git commit ... -$ git reset --hard HEAD~3 <1> ------------- -+ -<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad -and you do not want to ever see them again. Do *not* do this if -you have already given these commits to somebody else. (See the -"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for -the implications of doing so.) - -Undo a commit, making it a topic branch:: -+ ------------- -$ git branch topic/wip <1> -$ git reset --hard HEAD~3 <2> -$ git checkout topic/wip <3> ------------- -+ -<1> You have made some commits, but realize they were premature -to be in the "master" branch. You want to continue polishing -them in a topic branch, so create "topic/wip" branch off of the -current HEAD. -<2> Rewind the master branch to get rid of those three commits. -<3> Switch to "topic/wip" branch and keep working. - Undo add:: + ------------ @@ -255,6 +109,53 @@ remain there. <4> Then you can pull and merge, leaving frotz.c and filfre.c changes still in the working tree. +Undo a commit and redo:: ++ +------------ +$ git commit ... +$ git reset --soft HEAD^ <1> +$ edit <2> +$ git commit -a -c ORIG_HEAD <3> +------------ ++ +<1> This is most often done when you remembered what you +just committed is incomplete, or you misspelled your commit +message, or both. Leaves working tree as it was before "reset". +<2> Make corrections to working tree files. +<3> "reset" copies the old head to .git/ORIG_HEAD; redo the +commit by starting with its log message. If you do not need to +edit the message further, you can give -C option instead. ++ +See also the --amend option to linkgit:git-commit[1]. + +Undo a commit, making it a topic branch:: ++ +------------ +$ git branch topic/wip <1> +$ git reset --hard HEAD~3 <2> +$ git checkout topic/wip <3> +------------ ++ +<1> You have made some commits, but realize they were premature +to be in the "master" branch. You want to continue polishing +them in a topic branch, so create "topic/wip" branch off of the +current HEAD. +<2> Rewind the master branch to get rid of those three commits. +<3> Switch to "topic/wip" branch and keep working. + +Undo commits permanently:: ++ +------------ +$ git commit ... +$ git reset --hard HEAD~3 <1> +------------ ++ +<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad +and you do not want to ever see them again. Do *not* do this if +you have already given these commits to somebody else. (See the +"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for +the implications of doing so.) + Undo a merge or pull:: + ------------ @@ -376,6 +277,114 @@ $ git reset --keep start <3> <3> But you can use "reset --keep" to remove the unwanted commit after you switched to "branch2". + +DISCUSSION +---------- + +The tables below show what happens when running: + +---------- +git reset --option target +---------- + +to reset the HEAD to another commit (`target`) with the different +reset options depending on the state of the files. + +In these tables, A, B, C and D are some different states of a +file. For example, the first line of the first table means that if a +file is in state A in the working tree, in state B in the index, in +state C in HEAD and in state D in the target, then "git reset --soft +target" will put the file in state A in the working tree, in state B +in the index and in state D in HEAD. + + working index HEAD target working index HEAD + ---------------------------------------------------- + A B C D --soft A B D + --mixed A D D + --hard D D D + --merge (disallowed) + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + A B C C --soft A B C + --mixed A C C + --hard C C C + --merge (disallowed) + --keep A C C + + working index HEAD target working index HEAD + ---------------------------------------------------- + B B C D --soft B B D + --mixed B D D + --hard D D D + --merge D D D + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + B B C C --soft B B C + --mixed B C C + --hard C C C + --merge C C C + --keep B C C + + working index HEAD target working index HEAD + ---------------------------------------------------- + B C C D --soft B C D + --mixed B D D + --hard D D D + --merge (disallowed) + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + B C C C --soft B C C + --mixed B C C + --hard C C C + --merge B C C + --keep B C C + +"reset --merge" is meant to be used when resetting out of a conflicted +merge. Any mergy operation guarantees that the work tree file that is +involved in the merge does not have local change wrt the index before +it starts, and that it writes the result out to the work tree. So if +we see some difference between the index and the target and also +between the index and the work tree, then it means that we are not +resetting out from a state that a mergy operation left after failing +with a conflict. That is why we disallow --merge option in this case. + +"reset --keep" is meant to be used when removing some of the last +commits in the current branch while keeping changes in the working +tree. If there could be conflicts between the changes in the commit we +want to remove and the changes in the working tree we want to keep, +the reset is disallowed. That's why it is disallowed if there are both +changes between the working tree and HEAD, and between HEAD and the +target. To be safe, it is also disallowed when there are unmerged +entries. + +The following tables show what happens when there are unmerged +entries: + + working index HEAD target working index HEAD + ---------------------------------------------------- + X U A B --soft (disallowed) + --mixed X B B + --hard B B B + --merge B B B + --keep (disallowed) + + working index HEAD target working index HEAD + ---------------------------------------------------- + X U A A --soft (disallowed) + --mixed X A A + --hard A A A + --merge A A A + --keep (disallowed) + +X means any state and U means an unmerged index. + + Author ------ Written by Junio C Hamano and Linus Torvalds