基本用法
图中, History 即为本地仓库(local repository), Stage(Index) 为暂存目录, 也称为索引, Working Directory 为工作目录.
git add *file*
把Current Working Directory 下的file 放入 Stagegit commit
对 Stage 生成快照并放入 local Repogit reset -- *file*
用来将 Stage 恢复到上一次 commit 的状态(快照)git checkout -- *file*
把文件从 Stage 复制到 Current Working Directory, 并且丢弃本地修改
可以使用 git reset -p
, git checkout -p
, git add -p
进入交互模式.
可以跳过 Stage, 实现 Working Directory 和 Local Repo 的直接交流.
git commit -a
相当于运行git add
把Working Directory 下的文件放入 Stage 并 Commitgit commit *file*
进行一次包含最后一次 Commit, 并加上 Working Directory 快照的提交, 并且文件添加到 Stagegit checkout HEAD
从 Local Repo 中取出上一次 commit 的快照并回滚
图例
命令详解
Diff
查看两次提交之间的变动
Commit
执行 Commit 的时候, git 对 Stage 中的文件做一个快照, 提交给 local repo, 记为指向父节点的新节点, 然后把 HEAD 指向新节点,
图中执行 commit 后, stage 生成快照并提交给 repo, 记为新节点 f0cec, 其指向父节点 ed489, 同时 HEAD 从父节点转移至新节点.
即使当前分支是从某祖父节点出发的, git 也会生成新节点并指向该祖父节点, 并将 HEAD 指向新节点
图中 maint 在 commit 前是 master 的子父节点, 在 commit 不再是 master 的祖父节点, 此时合并或衍合是必须的.
如果想更改一次commit, 使用 git commit --amend
, git 会使用当前父节点进行一次新的提交, 新的子节点依旧指向该父节点, 旧的提交会被取消, 如图
Checkout
Checkout
用于从 Stage 中取出文件放到 Working Directory 中, 也可用于切换分支
当给定某个文件名时, git 会从指定的节点中拷贝文件到 Stage 和 Working Directory. 比如 git checkout HEAD~ foo.c
会从 HEAD~(即当前父节点)中拷贝 foo.c 文件到 Working Directory 并加到 Stage, 如果checkout
没有添加指定节点, 就会从 Stage 中拷贝文件.
如果不指定文件名, 而是给出一个本地分支名, 则会将 HEAD 指向该分支, 即转为 current branch
如果没有指定文件名和分支名, 而是一个标签, 远程分支, SHA-1值, 或者像是 master~3之类的东西, 则得到一个匿名分支, 称为 detached HEAD( 被分离的 HEAD 标识)
当 HEAD 处于分离状态时(不指向任何有名的 branch), commit 可以正常提交, 但不会更新任何有名的 branch( 称为新的匿名分支)
此时如果切换到其他分支, 就无法返回这个匿名分支
如果想对该匿名分支创建引用, 可以用 git checkout -b *name*
来创建一个指向匿名分支的新分支
Reset
reset
指令把当前分支指向另一个位置, 并且有选择的变动 Working Directory 和 Stage. 也用来从 Local Repo 中复制文件到 Stage, 不修改 Working Directory.
如果不给参数, 则当前分支指向那个节点, 并将 Stage 恢复到对应commit; 如果用 --hard
参数, 则 Working Directory 也恢复到该节点的commit, 如果用 --soft
参数, 则都不变
如果不提供版本号, 则默认 HEAD, 这样分支指向不变(依旧指向当前节点), 但是 Stage 会回滚到上一次 commit, 如果用了– hard, 则 Working Directory 也会回滚.
Merge
merge
将不同的 branch 合并, 合并前, 其他分支的Stage 必须和当前分支的 Stage 相同(即合并的几个分支需要有相同的 Stage).
- 如果另一个分支是当前分支的祖父节点, 则合并命令将什么也不做.
- 如果当前节点是另一个分支的祖父节点, 则带哦之 fast-forward 合并, 即简单易懂 HEAD, 并生成一个新的 commit
如果是一次真正的合并, 默认把当前节点(ed489)和另一个节点(33104)及他们的共同祖父节点(b325c)进行一次三方合并. 结果是先保存Working Directory 和 Stage, 然后在当前节点(ed489)处提交新的节点.
Cherry Pick
cherry-pick
命令”复制”一个提交节点并在当前分支做一次完全一样的新提交(将某节点作为新节点).
Rebase
衍合是合并命令的另一种选择. 合并吧两个父分支合并进行一次提交, 提交历史不是线性的. 衍合在当前分支上重演另一个分支的历史, 提交历史是线性的, 本质上是线性化的自动的 cherry-pick
上面所有的命令都在 topic 分支中进行, 而不是 master 分支( HEAD 指向 topic), 在 master 分支上重演, 并把分支指向新的节点(就得 topic 分支被回收).
要限制回滚返回, 使用 --onto
参数