Git 学习笔记

大概会以每天一次的频率持续更新。 暂停更新,手头有其他优先级更高的任务。

.gitignore

基本规则

每行一条规则,遵循 shell 使用的正则语法,以下是几点特殊规则:

举例(节选、演绎自此页):

# 忽略所有 .a 文件
*.a

# 但是不忽略 lib.a
!lib.a

# 只忽略当前目录下的 TODO 文件,但是不忽略 subdir/TODO
/TODO

# 忽略所有目录下的 file 文件,或者 file 目录
file

# 忽略所有目录下的 dir 目录,但是不忽略名为 dir 的文件
dir/

# 忽略 doc/notes.txt, 但是不忽略 doc/server/arch.txt
doc/*.txt

# 忽略 doc 目录及其任意层级子目录中的 .pdf
doc/**/*.pdf

其他注意点

Index 及工作区的管理

git checkout [source] [files]

用于探索不同版本,不影响 Commit 历史。

影响:

  1. HEAD 指针
  2. index
  3. 工作区

其行为模式可以分为两类:

1. 提供了文件名

2. 未提供文件名

不带任何参数的 git checkout 相当于一次 dry run,确保不会因为误操作导致现有工作被覆盖。

git reset [source] [files] [--<mode>]

用于取消历史修改,会影响 Commit 历史。

影响:

  1. 当前分支的指针
  2. HEAD 指针
  3. index (默认修改,可选)
  4. 工作区 (默认不修改,可选)

git reset 会修改 Commit 记录,这才是其核心作用,对 index、工作区的改动应当视为“副作用”。

默认来源为 HEAD,默认范围为所有文件,默认副作用为清空 index 的改动。

以下几个参数可以调整副作用的范围:

默认为 --mixed,即只恢复(清空)index。所以不带任何参数的 git reset 相当于清空 index(即取消 git add)。

git checkoutgit reset 的异同

这两者的核心语义都是:对于指定文件或者整个工作环境,回到指定 commit 改动产生之前的状态。而将该状态存入 index、工作区仅仅是命令的副作用。

两者都会影响 HEAD 指针跟 index工作区

git checkout 的功能倾向于临时性的探索,其会造成 HEAD 指针在不同的 Commit 记录之间挪动,仅限于挪动,不会修改 Commit 产生的历史链。副作用为默认对 index、工作区进行更改。

git reset 的功能倾向于永久性地撤回已经存在的 Commit 记录,会造成 HEAD 指针、当前分支指针同时变动。如果被撤回的这一部分 Commit 记录没被其他 Branch 所引用,则会永久丢失,不会在 Commit 历史中留下记录。副作用为默认仅对 index 进行更改。

配合图解理解一下:如,假设有两个分支 masterdevelop,当前处在 develop 分支,执行 git reset mastergit checkout master 之后所产生的结果如下:

image
reset checkout >original<

git checkoutgit resetgit revert 的一般用途

下表翻译自此页

命令作用级别一般用途
git checkoutfile舍弃其在工作区中的修改
git resetfile舍弃对文件修改内容的暂存(index)
git revertfileN/A
git checkoutcommit在分支之间切换 / 检查旧快照 / 舍弃工作区的修改
git resetcommit舍弃私有分支的commits / 舍弃暂存区(index)的修改
git revertcommit撤销公有分支的commits

git log & git diff

这里仅记录一些相对有用的选项,我也不怎么用它们,在这方面还是图形界面强。

git log

git diff


References & Further Reading

Copyrights

文中部分图片来源,版权归其原作者所有: