git Tips
00 Git配置
全局配置 ~/.gitconfig文件
项目配置 项目下的.git/config文件
别名配置
git配置文件中,增加alias部分,就可以使用诸如git last,git co等别名了
同时配置的其他全局变量如name和email也在这里
[alias]
co = checkout
ci = commit
br = branch
st = status
unstage = reset HEAD
last = log -1
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
[user]
name = user
email = [[email protected]]
Git使用
00 revert restore reset区别
git revert <commit>... 通过一个新的反向提交,来回退指定的commit提交(如果有冲突,需要先解决冲突)。
git-revert is about making a new commit that reverts the changes made by other commits.
git restore 从索引(默认)或者另外一个提交(--source commmitid)中还原工作区的文件。
git-restore is about restoring files in the working tree from either the index or another commit. ...
git reset 回退分支,移动HEAD位置,会影响提交记录。
git-reset is about updating your branch, moving the tip in order to add or remove commits from the branch.
01 暂存区=>还原=>工作区
提交到暂存区的文件,怎么还原到工作区(分批commit之类的场景)
-
git restore --staged <file>...git add命令之后,会提示,可以用这个命令,从暂存区中恢复到工作区,可以使用
git restore --staged -p来选择哪些文件从暂存区恢复,哪些不恢复 -
git rm --cached <file>...很直白的删除命令,删除暂存区中的文件,恢复到工作区
git rm命令的作用是从工作区和暂存区删除文件(不会实际删除文件) -
git reset HEAD <file>...相当于用版本库里的文件,覆盖掉暂存区和工作区的文件,默认的mixed模式(覆盖暂存区和工作区)
由于暂存区已经存在修改,所以回退就覆盖了暂存区的数据
02 版本库=>覆盖=>工作区
版本库中的文件,修改或者删除后,还未add,怎么干掉修改(开发了一部分代码,彻底不想 要了)
-
git restore <file>...git status会提示,可以使用这个方法,抹去工作区中的修改
-
git checkout -- <file>...直接从版本库检出文件,覆盖工作区
-
git reset --hard HEAD不能指定目录,把整个工作区修改都删掉,不能针对单个文件
03 抹掉commit
最后一次,或者某一次commit之后的提交,我们都不想要了(可能因为出错了或者其他什么原因)
-
git reset <mode> [commit]/HEAD^类似表达取消commit,把代码库HEAD指向commit或者HEAD^类似表达指定的那次commit上,之后的commit都取消掉。
mode有三种取值(说明被取消的commit怎么处理):
--soft所有被取消的commit,都恢复到add之后的状态,即版本库的提交,恢复到暂存区里,工作区没变化--mixed默认模式,所有被取消的版本库的提交恢复到工作区,要提交,需要重新add和commit--hard直接删除掉所有被取消的commit,无法再找回
04 强制覆盖远程分支
一般我们提交代码并推送到远程之后,如果我们本地再次修改,这时候如果继续用git push推送,会发现推送有问题
这时候直接用git push -f强制使用本地分支覆盖远程分支
05 时光机
在各个commit之间穿梭(指定HEAD位置,即当前版本),使用命令git reset --hard commit_id
往历史穿越,先用git log查看提交历史,确定要回退到的commit
往未来穿越,先用git reflog查看历史命令,找到要回到未来的哪个版本
06 merge体现
通常情况下,我们从master拉取一个feat分支,开发完成之后,如果使用merge方式,即在master分支上执行 git merge feat,如果没有冲突,会执行fast-forward,feat分支上的内容,直接接在原master节点后面,变成 原master -> commitid(feat,master)
如果我们删除掉了feat分支,那么除了看commit的comment,就没法知道原来的feat分支都有哪些提交,做了什么事情
但是如果我们使用git merge --no-ff -m 'merge feat 2 master' feat,就会生成一个新的commit,来体现我们从dev4合并到develop的过程。 相当于这个新的commit压缩了本分支的所有commit到一个commit里,并且接在了原master之后。

这样,在我么删除掉dev4之后,我们仍然能通过这新生成的一个commit知道该分支都干了什么。
07 git pull的两种模式
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
最佳实践:
1。通过git pull --rebase来保持当前分支拉到远程的更新(git fetch)之后,是通过rebase(git rebase)把本地的修改接在远程更新的commit之后,保持整个提交线图是一条直线,避免菱形(菱形是因为远程更新fetch到之后,执行了merge,在本地的commit之后产生了一个新的提交)
2。通过git mrege --no-ff -m 'br2 merge to br1' br1命令,人为的制造出一个分叉出来,表明这一系列提交都是为了实现同一个目的,刻意把提交内容弄成一次提交线图分叉。
08 git tag
git tag <taganme> -m "blablabla..." [commit id]用于新建一个标签,默认为HEAD,也可以指定一个commitid,-m刻意指定标签信息git tag可以查看所有标签git tag -d <tagname>可以删除一个本地标签git push origin :refs/tags/<tagname>删除远程标签git push origin <tagname>/--tags可以推送一个或者全部未推送的标签到远程
09 git branch
创建分支
git branch <branch-name> [<start-point>] 创建分支,start-point可选,如果不写,默认就是HEAD,如果写了,就是在指定的位置,比如HEAD3,HEAD^2~2(~HEAD的上一个节点,^2两个parent里的第二个,~2上两个节点)等。
git branch aaa 在当前节点处创建aaa分支
git checkout aaa切换到aaa分支,HEAD指向aaa
git checkout -b aaa在当前节点创建aaa分支,并且切换到aaa分支,即HEAD指向aaa,相当于一次执行了git branch aaa + git checkout aaa,一条命令相当于上面的两条。
强制修改分支位置
git branch -f main HEAD~3 把main分支强制指向他的3级parent节点
git branch -f 分支 xxx把名为【分支】的分支,指向xxx,这里的xxx可以是一个节点,也可以是分支名,也可以是HEAD等代表的相对路径
10 分离HEAD
HEAD 是一个对当前所在分支的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。
HEAD 总是指向当前分支上最近一次提交记录
HEAD 通常情况下是指向分支名的(如 bugFix)
分离的HEAD,就是让其指向某个具体的提交记录,而不是分支名,比如本来是
HEAD => main => C1 (HEAD指向main,main指向C1)
执行git checkout C1之后,HEAD指向了C1
所以git checkout xxx,就是把HEAD移动到某个地方
-
如果xxx是具体节点,就是把HEAD移动到该节点上
-
如果xxx是分支,就是把HEAD指向这个分支
另外,这里的xxx,可以用相对引用,比如HEAD^ bugFix~3,这样通过
git checkout命令,可以让HEAD随意在整个链上移动,可以通过HEAD本身相对定位,也可以通过分支名相对定位,也可以通过节点hash值绝对或者相对定位。
所以,不管是HEAD自己,还是节点hash值,还是分支名,只要有个锚点,就可以直接移动HEAD到指定的节点上去(可以通过^或者~n相对定位,也可以通过hash或者分支名绝对定位)。
在git命令里,所有需要指定节点或者分支的地方,本质都是需要节点,而节点可以通过上面说的相对位置或者绝对位置来指定
11 rebase重新认识
- 交互式rebase里,可以调整commit顺序
git rebase -i HEAD~4 交互式合并,把HEAD往前的4个节点,列出来,可以调整每个commit的顺序,调整到HEAD位置的commit,还可以用git commit --amend来修改,然后可以再用git rebase -i HEAD~4调整回原来的顺序,相当于对一系列提交中的某个节点进行修改,并移回原位。
- rebase可以支持两个参数
git rebase master feature,相当于get checkout feature + git rebase master
如果只写成git rebase master,相当于git rebase master current-branch
所以相当于 git rebase master [feature],如果feature是当前分支,可以省略,如果不是,相当于先checkout出feature,再执行rebase master操作。
12 git 远程
git fetch完成了两个动作