修补提交
有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend
选项的提交命令来重新提交:
git commit --amend
这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。
执行这个命令,文本编辑器启动后,可以看到之前的提交信息。 编辑后保存会覆盖原来的提交信息。
例如,你提交之后,发现忘记暂存某些需要的修改,可以向下面这样操作:
$ git commit -m '提交信息'
$ git add forgotten_file # 添加漏掉的暂存文件
$ git commit --amend # 可以修改提交信息然后重新提交
最终你只会有一个提交记录——第二次提交将代替第一次提交的结果。
这个操作最主要的还是修改提交信息,以免自己的仓库被提交信息弄乱了历史版本。
实战:
在之前的示例中,我们把readme.txt从仓库中删除之后,一直没有再添加到仓库中,现在正好用这个例子重新加入仓库。
先修改google.txt
文件,使用git add
加入暂存区,查看文件状态:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: google.txt
Untracked files:
(use "git add ..." to include in what will be committed)
readme.txt
使用git commit
提交:
$ git commit -m 'modify google.txt'
[master acf1451] modify google.txt
1 file changed, 2 insertions(+), 1 deletion(-)
将readme.txt
加入暂存区,然后使用git commit --amend
命令,可以看到上次的提交信息:
修改提交信息,输入法为英文状态下,按i
键,光标移到末尾修改提交内容,修改完成后,同样英文状态下,按下ESC
,然后输入:
,接着输入wq
保存退出,即可看到提交信息:
$ git commit --amend
[master 73d5592] modify google.txt and add file readme.txt
Date: Sat Sep 26 15:36:23 2020 +0800
2 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 readme.txt
查看最近一次的提交历史:
$ git log -1
commit 73d5592122fe5442f7c8a0398c44c1eda9ade985 (HEAD -> master)
Author: hahaha
Date: Sat Sep 26 15:36:23 2020 +0800
modify google.txt and add file readme.txt
取消暂存的文件
如果手抖,把本想分为两次独立提交的文件使用git add *
全部加入了暂存区,可以使用git reset HEAD
或者git restore --staged
来取消暂存,git status
命令其实也给出了提示:
我们再修改下readme.txt
文件,然后暂存,使用git status
命令查看:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: readme.txt
取消暂存的文件:
$ git restore --staged readme.txt
# 或者
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
# 查看状态,可以看到readme.txt又处于为暂存状态了
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
git reset
命令更多的用于回退版本(稍后讲),所以只是想取消暂存的文件,建议使用git restore --staged
命令
撤销对文件的修改
如果文件被改的一团糟了,这个时候想撤销全部更改,你可以使用git restore
来撤销更改
# 例如,我想撤销刚才readme.txt的更改
$ git restore readme.txt
此时查看文件内容,你会发现你所有的修改都被撤销了
在 git 中还可以使用git checkout --
命令撤销对文件的修改,例如:
$ echo 'test checkout -- command' >> readme.txt # 对readme.txt文件追加内容
$ git checkout -- readme.txt # 撤销修改
使用git checkout --
命令撤销修改,其实是 git 使用了最近提交的版本覆盖了它,git checkout
命令还有其他用途,稍有不慎,就会造成意外情况,所以慎用。
推荐使用git restore
命令来撤销修改,毕竟git自己推荐的
版本回退
讲这个之前,我们先进行3次提交,例如:
第一次修改readme.txt
文件,添加内容add version 1.0
,然后提交。
$ git commit -a -m 'readme.txt version 1.0'
第二次修改readme.txt
文件,添加内容add version 2.0
,然后提交。
$ git commit -a -m 'readme.txt version 2.0'
第三次修改readme.txt
文件,添加内容add version 3.0
,然后提交。
$ git commit -a -m 'readme.txt version 3.0'
现在来看看最近四次的提交历史:
$ git log --oneline -4
# commitID(可以简单的理解为版本号) 提交说明
0b1cde03e2ec38c4d43c090fa1d709894eb441a2 (HEAD -> master) readme.txt version 3.0
4b4566931f544da69ee1d6ef9d5c26af7e8108d8 readme.txt version 2.0
d3c72dd5ba02000c359d3b7b524250f42d3fade5 readme.txt version 1.0
73d5592122fe5442f7c8a0398c44c1eda9ade985 modify google.txt and add file readme.txt
如果现在我们要回退一个版本,也就是说,我现在需要回到readme.txt version 2.0
这个版本,就可以使用git reset --hard HEAD^
命令:
$ git reset --hard HEAD^
HEAD is now at 4b45669 readme.txt version 2.0
# 查看提交历史: 可以发现readme.txt version 3.0已经不见了
$ git log --pretty=oneline -4
4b4566931f544da69ee1d6ef9d5c26af7e8108d8 (HEAD -> master) readme.txt version 2.0
d3c72dd5ba02000c359d3b7b524250f42d3fade5 readme.txt version 1.0
73d5592122fe5442f7c8a0398c44c1eda9ade985 modify google.txt and add file readme.txt
6a1006ae257767ef55ee588cf9481eb49a369921 rename app.txt -> application.txt
# 查看readme.txt文件内容,之前添加的add version 3.0 也不见了,也就是说“时光倒流了”,版本确实回退了
$ cat readme.txt
Git is a version control system.
Git is free software.
Git has a mutable index called stage.
Git is so good
Linus is god
add app.txt file
add google.txt file
test git diff
add version 1.0
add version 2.0
HEAD在git中是一个特殊的指针,指向当前所在的本地分支,这里只有一个
master
分支,所以它指向的就是master
分支,在上面的提交历史也可一看到HEAD指向的是谁(HEAD -> master)。不理解没关系,后面分支还会讲到。
HEAD^
表示的是上一个版本,那么上上一个版本呢?可以写成HEAD^^
,那么要回到上10个版本怎么办?总不能写10个^
吧,其实可以写成这个HEAD~10
。当然如果要回退很多个版本,自己手动数是不可取的,这个时候,commitId
的作用就体现出来了,比如现在我们要回退到readme.txt version 1.0
这个版本,我们可以使用git reset --hard
:
$ git reset --hard d3c72dd
HEAD is now at d3c72dd readme.txt version 1.0
# 查看 readme.txt 内容 版本回退成功
$ cat readme.txt
Git is a version control system.
Git is free software.
Git has a mutable index called stage.
Git is so good
Linus is god
add app.txt file
add google.txt file
test git diff
add version 1.0
我们在使用commitId
时,可以不必要写完整的commitId
,通常使用8~10
个字符就可以精确指定到某个版本,如果怕产生歧义,就多写几位。
现在版本是回退成功了,那如果手抖,回退版本时,退的太多了怎么办?或者说,后悔了,想回到未来的某个版本怎么办,现在使用git log
也看不到回退前的commitId
了。那么我告诉你,这个世界上是没有后悔药的。
其他事不存在后悔药,但是git是有后悔药吃的。
git在后台会保存一个引用日志(reflog), 引用日志记录了最近几个月你的 HEAD 和分支引用所指向的历史。
你可以使用 git reflog
来查看引用日志:
$ git reflog
d3c72dd (HEAD -> master) HEAD@{0}: reset: moving to d3c72dd
4b45669 HEAD@{1}: reset: moving to head^
0b1cde0 HEAD@{2}: commit: readme.txt version 3.0
4b45669 HEAD@{3}: commit: readme.txt version 2.0
d3c72dd (HEAD -> master) HEAD@{4}: commit: readme.txt version 1.0
73d5592 HEAD@{5}: commit (amend): modify google.txt and add file readme.txt
......
通过这个日志,我们可以拿到我们回退前的commitId
。
那现在,我们可以回到“未来”去了:
$ git reset --hard 0b1cde0
HEAD is now at 0b1cde0 readme.txt version 3.0
#查看readme.txt 文件内容
$ cat readme.txt
Git is a version control system.
Git is free software.
Git has a mutable index called stage.
Git is so good
Linus is god
add app.txt file
add google.txt file
test git diff
add version 1.0
add version 2.0
add version 3.0