高级 1:不喜欢merge的分叉,用rebase吧
介绍的是 rebase
指令,它可以改变 commit
序列的基础点。它的使用方式很简单:
git rebase 目标基础点
需要说明的是,rebase
是站在需要被 rebase
的 commit
上进行操作,这点和 merge
是不同的。
高级 2:刚刚提交的代码,发现写错了怎么办?
用 commit --amend
可以修复当前提交的错误。使用方式:
git commit --amend
需要注意的有一点:commit --amend
并不是直接修改原 commit
的内容,而是生成一条新的 commit
。(但原commit
时间不变)
高级 3:写错的不是最新的提交,而是倒数第二个?
介绍了交互式 rebase
,它可以在 rebase
开始之前指定一些额外操作。交互式 rebase
最常用的场景是修改写错的 commit
,但也可以用作其他用途。它的大致用法:
- 使用方式是
git rebase -i 目标commit
; - 在编辑界面中指定需要操作的
commit
s 以及操作类型;- 目标是修改倒数第二个 commit,也就是上面的那个「增加常见笑声集合」,所以你需要把它的操作指令从 pick 改成 edit 。 edit 的意思是「应用这个 commit,然后停下来等待继续修正」
- 操作完成之后用
git rebase --continue
来继续rebase
过程。
高级 4:比错还错,想直接丢弃刚写的提交?
撤销最新的提交,方式是通过 reset --hard:
git reset --hard 目标commit
高级 5:想丢弃的也不是最新的提交?
这节的内容是「撤销过往的提交」。方法有两种:
- 用
git rebase -i
在编辑界面中 直接删除 想撤销的commit
s - 用
git rebase --onto
在 rebase 命令中直接剔除想撤销的commit
s
方法有两种,理念是一样的:在 rebase
的过程中去掉想撤销的 commit
,让他它消失在历史中。
高级 6代码已经 push 上去了才发现写错?
当错误的 commit
已经被 push
上去时的解决方案。具体的方案有两类:
- 如果出错内容在私有
branch
:在本地把内容修正后,强制push
(git push origin branch1 -f
)一次就可以解决; - 如果出错内容在
master
:不要强制push
,而要用revert
把写错的commit
撤销。
高级 7:reset 的本质——不止可以撤销提交
reset
指令的本质:重置 HEAD
以及它所指向的 branch
的位置。同时,介绍了 reset
的三种参数:
-
--hard
:重置位置的同时,清空工作目录的所有改动(git reset --hard HEAD^
); -
--soft
:重置位置的同时,保留工作目录和暂存区的内容,并把重置HEAD
的位置所导致的新的文件差异放进暂存区。 -
--mixed
(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。
除了上面这三种参数,还有一些没有列出的较为不常用的参数;另外除了我讲的功能外,reset
其实也还有一些别的功能和用法。不过 reset
最关键的功能、用法和本质原理就是上面这些了,想了解更多的话,可以去官网了解一下。
高级 8:checkout 的本质
checkout
的本质:签出(checkout)指定的 commit
。所以你不止可以切换 branch
,也可以直接指定 commit
作为参数,来把 HEAD
移动到指定的 commit
。
checkout 和 reset 的不同
checkout
和 reset
都可以切换 HEAD
的位置,它们除了有许多细节的差异外,最大的区别在于:reset
在移动 HEAD
时会带着它所指向的 branch
一起移动,而 checkout
不会。当你用 checkout
指向其他地方的时候,HEAD
和 它所指向的 branch
就自动脱离了。
事实上,checkout 有一个专门用来只让 HEAD 和 branch 脱离而不移动 HEAD 的用法:
git checkout --detach
执行这行代码,Git 就会把 HEAD 和 branch 脱离,直接指向当前 commit:
不常用。举个例子,比如你想在某个
commit
出写一些临时的新的 commit
s,但不确定是否保留这些内容(或者倾向于不保留),那么你就:1. 不希望把当前的 branch
带跑;2. 不想新建一个别的 branch。那么你就 detach
一下,这样就可以在后面的 commit
s 中只有 HEAD
在跟着 commit
s 跑,而 branch
一直留在原地。
高级 9:紧急情况:「立即给我打个包,现在马上!」
stash
指令可以帮你把工作目录的内容全部放在你本地的一个独立的地方,它不会被提交,也不会被删除,你把东西放起来之后就可以去做你的临时工作了,做完以后再来取走,就可以继续之前手头的事了。
-
git stash
工作目录暂时清理干净 -
git stash pop
切回分支
注意:没有被 track 的文件,即从没被 add 过的文件不会被 stash 起来,因为 Git 会忽略它们。如果想把这些文件也一起 stash,可以加上
-u
参数,它是--include-untracked
的简写
git stash -u
高级 10:branch 删过了才想起来有用?
- reflog :引用的 log
reflog
是 "reference log" 的缩写,使用它可以查看 Git 仓库中的引用的移动记录。
假如你误删了 branch1
这个 branch
,那么你可以查看一下 HEAD
的移动历史:
git reflog
切换回 删除前的分支sha1
,然后重新创建 branch1
:
git checkout c08de9a
git checkout -b branch1
- 查看其他引用的 reflog
reflog
默认查看 HEAD
的移动历史,除此之外,也可以手动加上名称来查看其他引用的移动历史,例如某个 branch
:
git reflog branch1