Git 版本管理的基本结构
- Working Tree :当前的工作区域
- Index/Stage :暂存区域,使用 git add xx,就可以将 xx 添加近 Stage 里面。(注意区分 stage 和 stash; git stash 命令暂存的地方不是 stage/index)
- Repository :版本库,提交的历史,即使用 git commit 提交后的结果
- Remote Repository:远程版本库,上面没有画,就是利用 github、Gitee 等将 repository 同步到云端
版本管理的基本命令
git revert
git revert -n <commit_id>
是用于“反做”某一个版本,以达到间接撤销该版本的修改的目的,它不会删除 repository 中的原有版本,相反会增加一个新版本。比如,我们 commit 了三个版本(版本一、版本二、 版本三),突然发现版本二不行(如:有 bug),想要撤销版本二,但又不想影响撤销版本三的提交,就可以用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西。
revert 如果之前(版本三)和之后(版本二)版本有改到同一个地方可能会触发冲突,需要手动解决冲突。
git rebase
git rebase
的功能是完成变基的操作,常常用来进行对 commit 进行整理,如合并多个 commit。常用的命令是 git rebase -i [startpoint] [endpoint]
用来交互式整理指定范围的 commit。运行之后会出现类似下面的界面,需要我们根据需求对其内容进行编辑:
上面未被注释的部分列出的是我们本次 rebase 操作包含的所有提交,下面注释部分是 git 为我们提供的命令说明。每一个 commit id 前面的 pick 表示指令类型,git 为我们提供了以下几个命令:
- pick:保留该 commit(缩写:p)
- reword:保留该 commit,但我需要修改该 commit 的注释(缩写:r)
- edit:保留该 commit, 但我要停下来修改该提交 (不仅仅修改注释)(缩写:e)
- squash:将该 commit 和前一个 commit 合并(缩写:s)
- fixup:将该 commit 和前一个 commit 合并,但我不要保留该提交的注释信息(缩写:f)
- exec:执行 shell 命令(缩写:x)
- drop:我要丢弃该 commit(缩写:d)
编辑完成后,保存退出。然后根据选择的设置,可能会继续提示我们修改确定注释内容,编辑完注释后再次保存退出,然后 commit 即可。
git reset
git reset 有三种模式,即 --soft
,--mixed
(默认),--hard
git reset --hard
:重置 stage 暂存区和 working tree 工作目录- 此模式会重置 repository 的 HEAD 到指定版本,同时也会重置清空 stage 区和工作目录里的内容为该版本对应的内容。换句话说,就是你的没有 commit 的修改(包括没有 add 的修改)会被全部擦掉,此时用
git status
查看状态就是nothing to commit, working tree clean
,类似于指定版本刚刚 commit 时的状态。 - 注意:此模式会清空当前没有 commit 的内容,谨慎操作
- 此模式会重置 repository 的 HEAD 到指定版本,同时也会重置清空 stage 区和工作目录里的内容为该版本对应的内容。换句话说,就是你的没有 commit 的修改(包括没有 add 的修改)会被全部擦掉,此时用
git reset --soft
:保留 stage 暂存区和 working tree 工作目录,并把重置 HEAD 所带来的新的差异放进暂存区- 此模式会重置 repository 的 HEAD 到指定版本,但是会保留当前工作区和暂存区的内容。此外由于版本回退而可能导致的 repository 和当前工作区的差异,也会被放置在暂存区。
- 当我们想合并「当前节点」与「reset 目标节点」之间不具太大意义的 commit 记录 (可能是阶段性地频繁提交) 时,可以考虑使用 soft 模式来让 commit 演进线图较为清晰点。此时
git reset --soft
相当于把「当前节点」与「reset 目标节点」之间的提交都重新放回暂存区,直接git commit
就可以把它们全部提交到一个新的 commit 里面。
git reset --mixed
或者git reset
:保留 working tree 工作目录,并把 stage 暂存区的内容退回给工作目录,此外重置 HEAD 所带来的新的差异也会被放入工作目录- 此模式会重置 repository 的 HEAD 到指定版本,但是会保留当前工作区的内容。暂存区内容(已经
git add
了的)会被退回给工作区(相当于git add
的逆操作)。此外由于版本回退而可能导致的 repository 和当前工作区的差异,也会被放置在工作区(git add
之前的状态)。简而言之,就是「把所有差异都混合(mixed)放在工作目录中」。
- 此模式会重置 repository 的 HEAD 到指定版本,但是会保留当前工作区的内容。暂存区内容(已经
版本撤销及常见场景
根据上述结构,Git 版本回退可以分为 4 种,即
- 工作区的代码想撤销
- add 到暂存区的代码想撤销
- 提交到本地仓库的代码想撤销
- 远程仓库的代码想撤销
工作区的代码想撤销
git checkout -- <file>
撤销当前工作目录中指定文件的修改
add 到暂存区的代码想撤销
git reset HEAD
将已经 add 到暂存区的代码撤销到工作区,即 add 操作的逆操作
提交到本地仓库的代码想撤销
可以利用 git reset --hard <版本号>
命令来实现版本回退,该命令中的版本号有几种不同的写法:
- 可以使用
HEAD^
来描述版本,一个^
表示前一个版本,两个^^
表示前两个版本,以此类推; - 也可以使用数字来代替
^
,比如说前 100 个版本可以写作HEAD~100
; - 也可以直接写版本号,表示跳转到某一个版本处。每次提交后,都会生成一个哈希码作为版本号,所以这里可以直接填版本号,哈希码很长,但是不用全部输入,只需要输入前面几个字符即可。
注意:此操作会直接将工作区,暂存区的当前内容清空,并撤回到指定回退版本的状态
远程仓库的代码想撤销
本地撤销后,push 到远程即可。可能会报错远程分支比当前本地分支超前,可以通过该 -f
参数强制 push 到远程。