
图来源:https://blog.osteele.com/2008/05/my-git-workflow/
git中有一棵树、两个区、两类指针
一棵树:版本树,它将代码的每个版本打包串起来,某些版本可能会有分支,他们就共同构成一棵树
两个区:工作区和暂存区
- 工作区:就是你当前项目目录
- 暂存区:版本树是一个大仓库,但我并不希望每次代码改动都做成一个版本提交到版本树中,而是希望按照实现的功能将多次改动共同作为一个版本提交,这个暂存区就是用来存储你的多次改动的地方
两类指针:HEAD指针和branch指针。他们分别指向版本树中的某个版本
- HEAD指针:你对代码的所有操作总是依赖于版本树中的一个版本的,而HEAD指针指的就是你当前工作的那个版本
- branch指针:你的代码有多个分支,每个分支总会有一个版本状态,branch指针就是说当前版本树的哪个节点表示这个分支
注:一般也会将暂存区和工作区也比作两棵树,我更乐意把他们看作两个代码缓冲区,因为他们没有版本的概念。就像两个大水池,你往里面放什么它就装什么,你往里面放哪个版本的代码,他就算是哪个版本。
例如:当你在暂存区存放了一些改动文件后,没有commit而切换到其他分支(git checkout branch),此时暂存区和工作区都会保持不变,只有HEAD指针会移动到新分支的branch指针所指向的版本上,你再commit的话就是将暂存区的代码提交到新分支上了
reset
git reset VERSION
用于同时修改HEAD指针和branch指针指向代码树中的版本(只要树中有的版本都可以指),你可以使用参数设置它是否要级联修改暂存区和工作区的代码
- –soft:只修改HEAD和branch指针。
此时暂存区和工作区保持不变。就是回滚到add之后,commit之前的状态
注:暂存区在commit之后并不会清空,而是保留commit时的代码快照 - –mix(默认):修改HEAD&branch指针和暂存区代码。
即将暂存区的代码修改为HEAD新指向的版本代码。即回滚到add之前的状态 - –hard:修改HEAD&branch指针和两个区的代码
使用该命令要注意,因为它会修改工作区的代码
git reset VERSION files
你可以选择只回滚部分文件到某个版本,但如此一来一个项目中的文件就可能属于不同版本了,而一个HEAD指针显然不可能指向多个版本
故当你只回滚部分文件时,HEAD指针并不会改变
除了HEAD指针不变外,其他还是一样的(即暂存区和工作区的级联改变)
git revert
git revert commitid
reset是将HEAD指针和branch指针重新指回之前的某个commit,而在该commit之后的commit都不要了
revert是指定回滚某一个commit,它只会回滚这一个commit中的代码,并且提交一个新的commit到版本库
reset的指针是往后走的,而revert的指针是往前走的
如果你要revert的某个commit与其后面的一些commit修改了相同的文件则会产生冲突,此时执行revert命令后,这些有冲突的文件就会有两个版本的代码,需要你手动进行处理,你可以使用 git revert –abort来撤销revert
checkout
git checkout 有两个作用,一是切换分支(checkout [version|branch]),二是恢复工作区文件状态(checkout files)
注:由于checkout功能比较混乱,后面又开发出 switch
和 restore
两个命令分别用来切换分支和恢复文件状态
git checkout VERSION 和 git reset –hard VERSION 命令很像,他们都会移动HEAD指针,修改暂存区和工作区,但它们又有很大不同
- 它只移动了HEAD指针而没有移动branch指针(若checkout的是某个版本而不是分支,则会出现branch指针和HEAD指针指向两个不同的版本,这就是指针分离)。你可以在指针分离的情况下修改代码创建新的branch,防止污染了原来的branch
git checkout VERSION file
也和 git reset –hard VERSION file相似,只不过也是不移动HEAD指针,暂存区和工作区还是会变的(不管暂存区和工作区是否有未提交的代码)
git checkout -- file
则是修改工作区文件状态,将工作区的file修改为暂存区的file,同 git restore file
。常用于回滚工作区文件。其中 --
的作用是消除歧义,用来指明后面跟的是file而不是branch
restore
用于恢复工作区和暂存区文件状态
git restore [--worktree] file
将工作区恢复到暂存区的状态,或者用 [-s|--source] commitID
指定从哪恢复到工作区
git restore --staged file
将暂存区恢复到HEAD状态,但不改变工作区(若要两个都改变,则将两个参数都加上)
switch
用于切换分支
git switch -c branch
切换分支,若不存在则创建(-c),若存在一个远程分支名相同,则也会自动切换到远程分支