文章目录
- 简介
- 前置概念
- reset
- [reflog 与 reset --hard](#reflog 与 reset --hard)
- revert(撤销指定提交)
- stash
- diff
- restore、checkout(代码撤回)
- merge、rebase、cherry-pick
简介
本文将介绍Git几个核心概念,和最常用的几个内容操作命令:
- reset
- diff
- restore、checkout
- stash
- reflog
- revert
- cherry-pick(merge、rebase)
前置概念
首先我们来看一下几个非常重要的前置概念
.git目录
sh
git init
我们执行上面命令就会生成一个.git目录
【工作区】add就到【暂存区】commit就到【本地仓库】
objects目录
objects目录中保存的是add到暂存区和commit到本地仓库的文件
refs目录
HEAD文件
HEAD是一个文本文件,你们内容是HEAD当前指向的分支:
ref: refs/heads/feature-view
reset
我们首先来看一下我们最常用的reset操作。
reset是重置,他重置的是commit
git reset [--soft | --mixed | --hard] HEAD
- --mixed:默认参数,撤销commit,所有commit和没有commit的代码放到工作区
- --soft:撤销commit,所有commit和没有commit的代码放到暂存区
- --hard:撤销commit,丢弃所有commit、工作区、暂存区代码
sh
# head表示当前版本,head^等价于head~1表示回退所有内容到上一个版本
git reset head^
# 回退2个版本
git reset head~2
# 将tree.txt这个文件的版本到上一个版本
git reset head^ tree.txt
# 回退到指定commit,commit-id:4889036387
git reset 4889036387
我们最最常用的reset的2个操作:
- 感觉自己的commit有点问题,想重新commit,这个也可以用git commit --amend
- 自己push之前有提交,导致push失败,pull之前要reset,这里可以用--soft参数,这样如果没有冲突就不用再add了
reset多个版本的这种操作不建议做,除非没有push到远程仓库,或者只有你一个人在提交代码。
如果修改了远程仓库的commit,通常push是不行的,必须使用git push -f。
git push -f是一个非常危险的操作,会导致push之前,其他人push的新代码丢失
git提示可以使用,是让我们知道自己在干什么,而不是告诉我们git push不行,用git push -f 吧。
一般来说,规范的团队都会把git push -f给禁用掉,不然一个人骚操作,代码丢了,可能啥证据都没有。
reflog 与 reset --hard
如果不小心执行了reset --hard,有机会补救吗?
sh
git reset --hard head~2
答案是还能抢救一下:
首先:
sh
git reflog
再使用git reset --hard回退到reset的上一个版本
sh
git reset --hard 8ca4549
commit的内容回来了,但是工作区和暂存区的内容掉了,找不回了
revert(撤销指定提交)
revert是用来将某次的commit的内容,提取出来到工作区。
这样就可以重新编辑,然后再一次提交。
主要使用场景就是:发现自己某一次提交有点问题,但是在这次提交之前已经有其他人提交了,怎么办呢?
可以用revert
sh
# 查看提交记录
git log --oneline
# 撤销指定的提交
git log revert b1c305d
revert并不会修改指定的commit,只会根据指定commit做逆操作
可以checkout到指定commit,看到内容并没有少:
sh
git checkout -b feature-view b1c305d
revert相当于将指定的commit合并到当前的head,还可能冲突。
所以,通常来说还不说直接改。唯一的作用可能就是记不清楚的commit的内容的时候,可以revert能自动帮你做。
stash
stash最常用的场景2个:
- 我们切分支的时候,有时候有修改不能切,就可以stash暂存
- pull代码冲突,就可以先stash 再pull
sh
# 默认暂存
git stash
# 添加暂存提示信息
git stash save "暂存提示信息"
# 查看暂存了哪些内容
git stash list
# 查看最上面的暂存修改了哪些文件
git stash show
# 查看第2个暂存修改了哪些文件
git stash show stash@{1}
# 查看最上面的暂存修改的具体内容
git stash show -p
# 查看第2个暂存修改的具体内容
git stash show stash@{1} -p
# 应用最上面的暂存,不删除
git stash apply
# 应用第2个暂存
git stash apply stash@{1}
# 应用最上面暂存,并删除(没有冲突才删除)
git stash pop
# 应用第2个暂存,并删除(没有冲突才删除)
git stash pop stash@{1}
# 删除最上面暂存
git stash drop
# 删除第2个暂存
git stash drop stash@{1}
# 删除所有暂存
git stash clear
diff
工作区与暂存区差异
sh
git diff
git diff b.txt
# 暂存区的文件在objects中,可以通过下面的命令查看
git cat-file -p 8fec8c3
# 工作区的对象还没有在objects中,会提示找不到对象
git cat-file -p 04a9f41
# 可以通过HEAD查看已经commit的对象
git cat-file -p HEAD:b.txt
git cat-file -p d1d06ad
暂存区与HEAD差异
暂存区(stage)HEAD是当前分支最新的commit
sh
git diff --cached
git diff --cached b.txt
工作区与HEAD差异
HEAD是当前分支最新的commit(通常就是master),也可以使用指定的commit-id
sh
git diff HEAD
git diff HEAD b.txt
# 工作区与指定commit的差异
git diff commit-id
其他比较
sh
# 查看两个commit之间的差异
git diff commit-id1 commit-id2
# 查看不同分支的文件差异
git diff branch-name1:file-path branch-name2:file-path
restore、checkout(代码撤回)
推荐使用restore,checkout还是让他去切分支吧。
restore是有递进关系:
- 可以从暂存区撤回到工作区使用--staged参数(相当于add的逆操作)
- 可以直接丢弃工作区的修改
sh
# 丢弃工作区的修改
git restore a.txt
# 等价于
git checkout a.txt
# 丢弃工作区和暂存区所有修改,不能指定文件,指定文件就等价于git checkout filename.txt
git checkout -f
# 将暂存区回退到工作区
git restore --staged a.txt
merge、rebase、cherry-pick
merge、rebase、cherry-pick主要是操作commit:
- merge合并代码,注意合并解决冲突就可以
- rebase,优化commit,注意修改的开始commit之后没有其他人的提交就可以(如果提示需要git push -f时一定要注意)
- cherry-pick是从其他分支挑选commit到当前分支
这里我们重点说一下cherry-pick,比如一个任务我已经开发了一段时间了,但是临时需要发一个修复版本,但是修复版本使用了我开发这段时间的代码,这么办呢?
这个时候就可以使用cherry-pick。
如果有冲突,先解决冲突:
继续cherry-pick:
sh
# 首先切到指定分支
git checkout b1
# 查看需要pick哪些提交
git log --oneline
# 切回到pick分支
git checkout master
# cherry-pick指定的commit
git cherry-pick 1f54b01 0fed6dd
# 如果有冲突手动解决冲突,然后add
git add .
# 继续cherry-pick处理commit信息
git cherry-pick --continue