0%

Git:git-reset的用法总结

概要

Git:git-reset的用法总结。

博客

博客地址:IT老兵驿站

前言

Git reset感觉是相当复杂的一个指令,用了快一年了,总感觉还没有用明白,所以,需要好好总结一下。

语法

1
2
3
git reset [-q] [<tree-ish>] [--] <paths>…​
git reset (--patch | -p) [<tree-ish>] [--] [<paths>…​]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

这个命令有三种用法,前两种用来从<tree-ish>所指定的地方拷贝条目到index区域。
其实这个是说从仓库的某一个版本获取到index区域,感觉这个用法更多是用在了对于git add等操作的逆向操作。

第三种格式,将当前分支的HEAD指针设定为<commit> 这个提交号,同时可以选择性地修改index和工作区域。

tree-ish是什么意思呢?要参考这里,是Git所使用的指明路径的语法。类似以下这样的格式:

1
2
3
<rev>:<path>, e.g. HEAD:README, :README, master:./README

A suffix : followed by a path names the blob or tree at the given path in the tree-ish object named by the part before the colon.

是指某个版本的某个文件,或者某个分支的某个文件。

用法1

git reset [-q] [<tree-ish>] [--] <paths>…​

This form resets the index entries for all to their state at . (It does not affect the working tree or the current branch.)

This means that git reset is the opposite of git add .

After running git reset to update the index entry, you can use git-checkout[1] to check the contents out of the index to the working tree. Alternatively, using git-checkout[1] and specifying a commit, you can copy the contents of a path out of a commit to the index and to the working tree in one go.

这个用法将index区域所有符合的条目修改为<tree-ish> 的状态。(这并不影响工作目录或者当前分支。)
这个reset是更新index条目,更新后,可以从index中通过checkout指令获取内容到工作目录。如果git checkout指定了一个提交号,那么就可以根据这个提交号更新内容到index和工作目录。

关于ORIG_HEAD的介绍:需要参考这里

HEAD is (direct or indirect, i.e. symbolic) reference to the current commit. It is a commit that you have checked in the working directory (unless you made some changes, or equivalent), and it is a commit on top of which “git commit” would make a new one. Usually HEAD is symbolic reference to some other named branch; this branch is currently checked out branch, or current branch. HEAD can also point directly to a commit; this state is called “detached HEAD”, and can be understood as being on unnamed, anonymous branch.

And @ alone is a shortcut for HEAD, since Git 1.8.5

ORIG_HEAD is previous state of HEAD, set by commands that have possibly dangerous behavior, to be easy to revert them. It is less useful now that Git has reflog: HEAD@{1} is roughly equivalent to ORIG_HEAD (HEAD@{1} is always last value of HEAD, ORIG_HEAD is last value of HEAD before dangerous operation).

For more information read git(1) manpage, Git User’s Manual, the Git Community Book and Git Glossary

HEAD是指当前分支上当前的提交号。
ORIG_HEAD 是指上一个HEAD所指向的提交号。
这其实是两个指针,第二个指针的设计其实是为了做保护,一旦第一个指针被误操作了,还有机会去挽回。

实例:
将发生改变的文件 _config.yml加入index

1
$ git add _config.yml

这样_config.yml 文件就被加入到index区域中,显示成:

1
2
3
4
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: _config.yml

撤销上面的操作,恢复_config.yml为版本库中的状态:

1
$ git reset _config.yml

这种用法相当于<tree-ish>的参数设置为HEAD

用法2

git reset (--patch | -p) [<tree-ish>] [--] [<paths>…​]

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, i.e. you can use it to selectively reset hunks. See the “Interactive Mode” section of git-add[1] to learn how to operate the –patch mode.

这个用法是以patch 的方式展示出来需要reset的代码, git reset -pgit add -p 就是一对互为反向的操作,后者是把工作目录下变更的代码以patch 的方式展示出来,以互动的方式应用到index上,前者则是一个反向操作。

实例:
将发生改变的文件 _config.yml加入index

1
$ git add -p  _config.yml

撤销上面的操作:

1
$ git reset -p  _config.yml

可以看到,这种用法相对上面那一种用法其实是增加了互动的提醒。

用法3

git reset [<mode>] [<commit>]

This form resets the current branch head to and possibly updates the index (resetting it to the tree of ) and the working tree depending on . If is omitted, defaults to “–mixed”. The must be one of the following:

这个用法是用来设置当前的分支的HEAD指针,或者index 的指向当前版本的指针,或者工作空间指向当前版本的指针。

–soft
Does not touch the index file or the working tree at all (but resets the head to , just like all modes do). This leaves all your changed files “Changes to be committed”, as git status would put it.

soft参数用来设置HEAD指针。

–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.

mixed参数用来设置index指针,文件的修改仍然会被保留,但是没有纳入到index中。

If -N is specified, removed paths are marked as intent-to-add (see git-add[1]).

–hard
Resets the index and working tree. Any changes to tracked files in the working tree since are discarded.

hard重置index和工作区域,所有在这个<commit>之后的修改将被丢弃。

–merge
Resets the index and updates the files in the working tree that are different between and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added). If a file that is different between and the index has unstaged changes, reset is aborted.

In other words, –merge does something like a git read-tree -u -m , but carries forward unmerged index entries.

merge重置index ,并且更新那些工作区的文件(在<commit>HEAD中不同的)。这个还需要进一步理解一下。

–keep
Resets index entries and updates files in the working tree that are different between and HEAD. If a file that is different between and HEAD has local changes, reset is aborted.

If you want to undo a commit other than the latest on a branch, git-revert[1] is your friend.

实例 版本库中的提交如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
commit cac453cf6501c3ea3b626636bc4399ed48704543 (HEAD -> master, origin/master, origin/HEAD)
Author: xxx <xxx@xxx.xxx>
Date: Fri Jul 27 18:08:46 2018 +0800

从版本库中移除项目配置文件和日志配置文件

commit cd36b7297106a871ae331f487179fd5584fb38cd
Author: xxx <xxx@xxx.xxx>
Date: Fri Jul 27 18:06:37 2018 +0800

暂时参考原来的逻辑,使用硬编码的方式,新增了权限

commit 24f19e80b5b8e2c05faf04706d95b5ac538ddbdd (f_1486)
Author: xxx <xxx@xxx.xxx>
Date: Wed Jul 11 22:00:43 2018 +0800

修改了login的登录按钮的宽度

commit e948bb044676ff917be862d9fae8391ba1b82351
Author: xxx <xxx@xxx.xxx>
Date: Tue Jul 10 23:39:28 2018 +0800

完成初步的修改

现在发现最后三次提交是存在问题的,不应该直接提交到master上,这个时候需要把HEAD指针恢复到倒数第四次提交上。

1
git reset --soft e948bb044676ff917be862d9fae8391ba1b82351

这样后面三次提交的改变从版本库还原出来,变成尚未提交的状态,这样我们就可以新开一个临时的dev分支,继续我们之前的工作(参考Git Flow一篇文章)。