基本用法

Git基本用法
图中, History 即为本地仓库(local repository), Stage(Index) 为暂存目录, 也称为索引, Working Directory 为工作目录.

  • git add *file* 把Current Working Directory 下的file 放入 Stage
  • git commit 对 Stage 生成快照并放入 local Repo
  • git 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 的直接交流.
跳过 Stage

  • git commit -a 相当于运行 git add把Working Directory 下的文件放入 Stage 并 Commit
  • git commit *file* 进行一次包含最后一次 Commit, 并加上 Working Directory 快照的提交, 并且文件添加到 Stage
  • git checkout HEAD 从 Local Repo 中取出上一次 commit 的快照并回滚

图例

图例

命令详解

Diff

查看两次提交之间的变动
diff

Commit

执行 Commit 的时候, git 对 Stage 中的文件做一个快照, 提交给 local repo, 记为指向父节点的新节点, 然后把 HEAD 指向新节点,
commit
图中执行 commit 后, stage 生成快照并提交给 repo, 记为新节点 f0cec, 其指向父节点 ed489, 同时 HEAD 从父节点转移至新节点.

即使当前分支是从某祖父节点出发的, git 也会生成新节点并指向该祖父节点, 并将 HEAD 指向新节点
git
图中 maint 在 commit 前是 master 的子父节点, 在 commit 不再是 master 的祖父节点, 此时合并或衍合是必须的.

如果想更改一次commit, 使用 git commit --amend, git 会使用当前父节点进行一次新的提交, 新的子节点依旧指向该父节点, 旧的提交会被取消, 如图
amend

Checkout

Checkout用于从 Stage 中取出文件放到 Working Directory 中, 也可用于切换分支

当给定某个文件名时, git 会从指定的节点中拷贝文件到 Stage 和 Working Directory. 比如 git checkout HEAD~ foo.c 会从 HEAD~(即当前父节点)中拷贝 foo.c 文件到 Working Directory 并加到 Stage, 如果checkout 没有添加指定节点, 就会从 Stage 中拷贝文件.
checkout

如果不指定文件名, 而是给出一个本地分支名, 则会将 HEAD 指向该分支, 即转为 current branch
checkout

如果没有指定文件名和分支名, 而是一个标签, 远程分支, SHA-1值, 或者像是 master~3之类的东西, 则得到一个匿名分支, 称为 detached HEAD( 被分离的 HEAD 标识)
checkout

当 HEAD 处于分离状态时(不指向任何有名的 branch), commit 可以正常提交, 但不会更新任何有名的 branch( 称为新的匿名分支)
commit

此时如果切换到其他分支, 就无法返回这个匿名分支
commit

如果想对该匿名分支创建引用, 可以用 git checkout -b *name* 来创建一个指向匿名分支的新分支
commit

Reset

reset 指令把当前分支指向另一个位置, 并且有选择的变动 Working Directory 和 Stage. 也用来从 Local Repo 中复制文件到 Stage, 不修改 Working Directory.

如果不给参数, 则当前分支指向那个节点, 并将 Stage 恢复到对应commit; 如果用 --hard 参数, 则 Working Directory 也恢复到该节点的commit, 如果用 --soft 参数, 则都不变
reset

如果不提供版本号, 则默认 HEAD, 这样分支指向不变(依旧指向当前节点), 但是 Stage 会回滚到上一次 commit, 如果用了– hard, 则 Working Directory 也会回滚.
reset

Merge

merge 将不同的 branch 合并, 合并前, 其他分支的Stage 必须和当前分支的 Stage 相同(即合并的几个分支需要有相同的 Stage).

  • 如果另一个分支是当前分支的祖父节点, 则合并命令将什么也不做.
  • 如果当前节点是另一个分支的祖父节点, 则带哦之 fast-forward 合并, 即简单易懂 HEAD, 并生成一个新的 commit
    merge

如果是一次真正的合并, 默认把当前节点(ed489)和另一个节点(33104)及他们的共同祖父节点(b325c)进行一次三方合并. 结果是先保存Working Directory 和 Stage, 然后在当前节点(ed489)处提交新的节点.
merge

Cherry Pick

cherry-pick 命令”复制”一个提交节点并在当前分支做一次完全一样的新提交(将某节点作为新节点).
cherry-pick

Rebase

衍合是合并命令的另一种选择. 合并吧两个父分支合并进行一次提交, 提交历史不是线性的. 衍合在当前分支上重演另一个分支的历史, 提交历史是线性的, 本质上是线性化的自动的 cherry-pick
rebase

上面所有的命令都在 topic 分支中进行, 而不是 master 分支( HEAD 指向 topic), 在 master 分支上重演, 并把分支指向新的节点(就得 topic 分支被回收).

要限制回滚返回, 使用 --onto 参数
rebase