Git

1. 对象模型

  • Git由一堆对象组成,每个对象都有一个SHA1的40位编码
  • 每个文件都是一个blob,由内容进行hash,同样内容的文件在版本库内只有一份
  • 每个目录都是一个tree,tree中可以有tree也可以有blob。(文件名等信息在tree中保存)
  • 每个commit都指向一个tree,一个或多个parent,包含作者,email,日期,消息等数据。(tag就是一个commit的引用而已)
  • Git Repo就是由commit组成的网络

既然如此,我们就得找到表示commit的方式

2. Commit的表示法

基础

  • branchname : 访问branchname最新的commit
  • tagname : 访问tagname引用的commit
  • HEAD
  • 完整的hash
  • hash的前几位(7位一般就够了)

组合

  • name^ : name的parent commit
  • name^ : parent的parent
  • namen : 第 n 个 parent(在merge的情况下)
  • name~n : 倒数第 n 个 parent
  • name:path : commit中的文件

范围

  • name1..name2 : name2能回溯到的,但是name1不能回溯到的(master..,相当于 mater..HEAD,当前分支的修改)
  • name1...name2 : name1的和name2的祖先,但不是共同祖先

描述

--since="two weeks ago"
--until="1 week ago"
--grep=pattern
--committer=pattern
--author=pattern
--no-merges

3. 三个位置

Working Tree

当前的工作目录,包含文件。git add以后,进入 index

Index

暂存区。所谓 index 是指,暂存区里包含了各种新增 object 的引用(索引)。git commit以后,进入 branch。

Branch

当前的分支。

4. 部分操作

config

在使用 git 前必须设置好名字和邮箱,如果不用 global 参数,则是设置项目专用的作者信息。

$ git config --global user.name 'Your Name'
$ git config --global user.email you@somedomain.com

add

将文件从 working tree 添加到 index
bash
git add <path> # 新增,修改的文件(文件夹)
git add -u <path> # 修改,删除的文件(文件夹)
git add -A <path> # 新增,修改,删除的文件(文件夹)

commit

将 index 的 tree 作为下一个 commit,加入当前 branch。
bash
git commit -m 'my commit message..'
git commit -a # 先 add 再 commit (-am)
git commit --amend -m "correct some error" # amend产生新的ID,请不要amend和别人共享的commit

diff

git diff # unstaged change
git diff --cached # difference between index and branch
git diff HEAD # diff between working tree + index and branch

checkout

# 注:忽略未commit的文件,--force参数可以暴力覆盖

git checkout <branch>  # 更新三棵树和HEAD
git checkout <commit>  # 更新HEAD和working tree
git checkout           # 用 last commit 或 index 来复位 working tree

reset

reset 指令不是单纯修改HEAD(与checkout不同),而是先修改branch,然后把HEAD指向新的branch。

git reset --soft  # 只修改 branch
git reset --mixed # 默认,修改 branch + index 
git reset --hard  # 修改 branch + index + working tree