git 常用命令笔记
提示
git 是现如今最火的版本控制工具,尽管已经使用了 GitHub 数年的时间了,但一直没有对 git 命令以及作用进行深入的分析和学习,对 git 的使用还仅停留在 add、commit、push、clone 上,这根本算不得掌握 git。因此,这次一得出空来就开始从头恶补 git 知识了,分享出来与大家一同学习进步。
文件指针
- git log 可以查看历次提交信息,其中就有每一次提交的 hash 值,这对每一次提交都是唯一的文件指针。hash 可以用短 hash 值表示,只需要在 git log 后加上--abbrev-commit 参数即可。
- HEAD 是一个特殊的文件指针,它指向当前工作区版本的位置。
- ^和~的意思都是指向该版本的父提交,如 HEAD^与 HEAD~其实是等价的,但是~2 与^^等价,与^2 不等价,^2 指的是该版本的第二个父提交版本(因为在 merge 过后一个文件版本会有多个父版本)。
文件版本控制操作
git add < file > // 将文件的修改从工作区添加至暂存区 (staged)
git rm < file > // 将删除文件这样一个修改操作提交到暂存区
git commit // 将暂存区的所有修改提交入库
-m 参数 填写提交内容的说明。
--amend 表示回退最近一次 commit 重新编写内容说明。
-a 相当于自动做了一次
git add .
操作。git checkout -- < file >
checkout 命令有两种作用,后面加上 -- (注意两边都有空格,是一个独立参数)后的意思是,将文件同步成版本库中最新的状态。相当于取消当前工作区的所有更改。但是这个操作不会影响暂存区 (staged) 中的内容。
这对本地已经删除但还没有 git rm 的文件同样适用,能够恢复本地工作区的文件。需要注意的是,此操作不可逆,工作区的修改中的文件内容将无法恢复。
但如果要修改的文件已经在暂存区的话,无论是 git add 还是 git rm,就只能通过 git reset 恢复了,接下来介绍。
git checkout 的另外一种意思在下面介绍。
更新:git2.23 新增语法糖
git restore
命令,更语义化的本地修改撤销操作。git restore < file >
作用效果与git checkout -- < file >
相同,都是表示将工作区的修改全部取消。而若加入--staged 参数,则是表示将缓存区的文件撤销回工作区的意思,等价于
git reset HEAD
。git reset < hash >
这是个功能及其强大也及其复杂的命令。它表示在本地库回滚状态。
它主要有三种参数,分别代表三种不同效果的回滚。
--hard,是 git 中少有的几个会丢失信息的操作,它代表将该版本库中的内容强制覆盖本地文件,使得暂存区和工作区的状态强制与该版本同步。该操作不可逆,会使得你正在工作区和暂存区的文件修改完全丢失。不仅如此,被你回退之前的版本将会剔除出提交树中,不会显示在版本控制信息里,版本将无法回溯。因此慎用!非要使用的话最好先 git stash 缓存一下。
还有一种用法,如果我们希望彻底丢掉本地修改但是又希望保留当前 branch 所指向的版本的话,直接 git reset --hard HEAD 即可。
(当然,非要找回还是有办法的,使用 git reflog 查找那个版本的 hash 再 git reset 回来即可)
--soft,它使得文件的状态与 HEAD 指针都回退到指定版本的位置,并且同时,当前处于工作区和暂存区的文件都不会做任何更改。所有的在 HEAD 节点和你重置到的那个版本之间的所有变更集都放在暂存区中。
--mixed,为 git reset 的默认参数,混合了--hard 与--soft 的特点,它也将文件的状态与 HEAD 指针都回退到指定版本的位置,但只将暂存区与该版本强制同步,工作区的内容不会被更改。并且它也不会剔除
git stash // 修改代码的临时存储
对于还没有 commit 但是被 git 跟踪到了的代码,如果需要临时存储一下可以使用
git stash
命令,会建立一个栈来存储当前的修改代码。需要恢复时,可以使用
git stash pop
恢复最后一次临时存储的代码。若想恢复其他时间存储过的代码,使用git stash list
查看所有被临时存储了的代码,然后找到某一次存储的 stash id,然后使用git stash drop stash@< id >
来进行恢复。加入--include-untracked 参数可以存储未被加入 git 跟踪的代码。
使用
git stash clear
删除所有被临时存储的 stash 记录。git merge < branch > // 将该分支合并进当前分支
这里的 merge 分
fast-forward
和recursive
等模式,但 git 都能自动匹配最佳方案,就不提了。要注意的是,合并过程中可能产生文件冲突。这时,当前分支会变为名叫
<branch>|MERGING
的临时分支,需要手动解决后,使用git merge --continue
,才能产生新的合并提交。若要取消这次合并,使用git merge --abort
即可。git rebase < hash > // 分支历史的变基
这个命令是在不希望产生合并的分支历史的特殊要求下使用的,对清理出一条干净的 git 提交线非常有帮助。
加入-i 参数增加分布操作,能够使操作图形化,推荐使用时添加。
命令参数:
p, pick <提交> = 使用提交
r, reword <提交> = 使用提交,但修改提交说明
e, edit <提交> = 使用提交,进入 shell 以便进行提交修补
s, squash <提交> = 使用提交,但融合到前一个提交
f, fixup <提交> = 类似于 "squash",但丢弃提交说明日志
x, exec <命令> = 使用 shell 运行命令(此行剩余部分)
b, break = 在此处停止(使用 'git rebase --continue' 继续变基)
d, drop <提交> = 删除提交
l, label < label > = 为当前 HEAD 打上标记
t, reset < label > = 重置 HEAD 到该标记
m, merge [-C < commit > | -c < commit >] < label > [# < oneline >] 创建一个合并提交,并使用原始的合并提交说明
git push < remote > < branch > // 将本地某个分支的更新推送到远程
其中本地分支名可以与远程分支名不同步,将< branch >部分改写为
<本地分支名>:<远程分支名>
即可。这里还有一个特殊操作,如果不指定本地分支名,像是
:<远程分支名>
这样,表示删除该远程分支。比较常用的参数如下:
-u,指定当前推送的主机为默认主机,这样后面就可以不加任何参数使用
git push
。不带任何参数的git push
,默认只推送当前分支。-d 或--delete,删除该远程主机的该分支。如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。
-f 或--force,当你需要提交一个有文件冲突的版本,需要本地强制覆盖远程时,使用这个参数,它将在远程主机产生一个”非直进式”的合并 (non-fast-forward merge)。
--all,不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机。
--tags,推送时将本地的 tags 标签也推送上去(默认不推送)。
git pull < remote > < branch > // 取回远程主机某个分支的更新。
功能相当于同时执行了git fetch
与git merge
。参数大致与git push
相同,就不多做介绍了。
- git revert < hash > // 分支的回滚操作
与git reset
的区别在于 revert 不会更改或删除原有的提交记录,反而会生成一条新的提交。对于线上代码或者多人使用的回滚来说一定要使用 revert 而不是 reset,尽量不要修改多人合作分支的时间线。
加入-n 参数能将多次回滚,合并成一次 commit。如果不加-n,回滚了多少条 commit 就会新生成多少条 commit。
状态信息查看操作
git remote // 列出所有远程主机。
-v
选项,可以参看远程主机的网址。git remote add <主机名> < git 地址 >,添加远程主机。
git remote rm <主机名>,删除远程主机。
git branch // 查看该版本的所有分支
默认只查看本地分支。
-r
选项,可以用来查看远程分支,-a
选项查看所有分支。git branch < branch >
表示新建分支。(若分支已存在,则报错。)
git checkout < branch >
又是这个命令,但是注意,这一次没有
--
命令,它表示将工作区跳转到该分支上。若不存在该分支,可以使用
-b
参数新建该分支并跳转到该分支上。git status // 查看当前的工作区和暂存区文件修改
git reflog // 查看该分支的历史提交记录
到目前我发现它最有用的地方就是记录了我
git reset --hard
之前的版本 hash,可以让我恢复版本。git log // 查看该分支的提交记录
如果跟我一样不太喜欢用 gitk 这样的 GUI 的话,我提供几个常用参数作参考。参数对 gitk 也适用。
--oneline 给我的感觉相当于--pretty=oneline 与--abbrev-commit 的结合,只显示提交 ID 和提交信息的第一行。
--all 显示所有分支的信息。
--decorate 标记让 git log 显示指向这个提交的所有引用(比如说分支、标签等)。
--graph 选项绘制一个 ASCII 图像来展示提交历史的分支结构。
-[number],表示只显示最后提交的若干列信息。
gitk // git log 的图形化界面版本