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