Git 的本质是一个可追踪历史的标签式文件系统. 它的基本元素包括对象和引用两种.
Git 的对象由键值内容对组成. 通过
find .git/objects -type f
可以查看所有对象的键值, 键值的前两个字符为目录, 剩余字符为文件.
Git 对象包括四种类型.
通过
git cat-file -t
可以查看对象类型. blob 对象通常保存文件, 而 tree 对象则保存目录. 暂存区 index 就是一个 tree 对象. 当用户调用 git commit 时, 会产生一个 commit 对象. commit 对象的内容包括
当用户调用 git tag -a 时, 会产生一个 tag 对象. tag 对象的内容包括
通过
git cat-file <key>
可查看普通对象内容. 通过
git ls-tree <key>
可查看 tree 对象的内容. 通过
git commit-tree <tree> [(-p <parent>) ...] -m "message"
可以手动提交一个 commit 对象. 其中, parent 依次列出该对象的每个 parent commit 对象. message 为提交的 log 信息.
Git 引用包括三种类型.
普通引用就是一个指向 Git 对象的指针. 而符号引用就是一个指向 Git 普通引用的指针. 所有引用保存于
.git/refs
中. 分于三个目录中保存.
.git/refs/heads/
.git/refs/tags/
.git/refs/remotes/
其中, heads 中包含了所有的 branch, 其中的引用就指向每个开发分支的最前沿, 每次调用 git commit, heads 中以相应分支命名的引用都会移动到最新提交的 commit 对象. tags 中包含了所有的 tag, 即通过 git tag 生成.
通过命令
git update-ref refs/heads/test [cac0ca]
可以查看普通引用 refs/heads/test 或创建一个指向 cac0ca 对象的普通引用. HEADS 是个符号引用, 指向当前 branch 的最新提交的对应 heads 引用. 通过
git symbolic-ref HEAD refs/heads/test
可以查看或创建符号引用. 当使用 git tag 时, 会在 tags/ 中创建一个普通引用, 指向用户指定的 commit 对象. 当使用 git tag -a 时, 会先创建一个以用户指定的 commit 对象为指针的 tag 对象 (同时还包含时间, message 等辅助信息), 然后再在 refs/tags/ 中创建一个指向上述新建 tag 对象的普通引用.
远程引用全部保存于 .git/refs/remotes/ 中. 其下一级目录为远程 git repository 的名称 (例如 origin). 每个远程引用代表远程 repository 中的一个 heads 或 tags 引用.
每个引用都可以使用后缀 ~n 语法指定第几辈祖先. 用 ^n 语法指定第几个 parent.
^ = ~1
^^ = ~2
git 还会记录所有引用修改的历史. 通过
git reflog --date=iso
可以查看该历史, 从而跟踪 git 提交的过程和时间.
查看本地工作目录状态
git status -uno -s
查看当前 branch 的相关历史
git log --graph [--oneline] --author=...
--graph 用于以图的方式显示历史. --oneline 用于把每条历史显示在一行内. --author= 用于根据 author 过滤信息.
查看某个特定文件的修改历史
git log -p <file_path>
切换 branch
git checkout <branch_name>
新建 branch
git branch <branch_name>
查看 branch 信息
git branch -vv -a
-vv: 包含对远程 branch 的跟踪状态, -a: 包含远程 branch 本身.
建立远程引用
git remote add <remote_name> <remote_url>
在本地新建一个跟踪到远程 branch 的 branch, 并切换到该 branch.
git checkout -b [branch] [remotename]/[branch]
git checkout --track [remotename]/[branch]
设置当前本地 branch 跟踪到远程 branch.
git branch -u origin/serverfix
重命名一个 branch
git branch -m <old_name> <new_name>
从远程 repository 中获取数据
git fetch <remote> [refspec]
其中 remote 为远程 repository 名字. refspec 为如下格式
[+]<src>:<dst>
src 为远程 branch, dst 为本地 ref 路径 (refs/..., 通常省略, 从而默认为 refs/remotes/<remote>/<branch>), 如果省略 refspec, 则 fetch 所有远程 branch (不推荐). + 表示强制取回 (不推荐). 从而通常形式为
git fetch <remote> <branch>
合并某个 branch (本地或远程) 到当前 branch.
git merge <branch|remote/branch>
仅合并某个 branch 到当前工作目录, 不提交.
git merge --no-commit --no-ff <branch|remote/branch>
取消 merge 状态, 恢复为普通工作目录. (merge 途中无法执行 git commit --amend, 且存在未提交到 index 的修改)
git update-ref -d MERGE_HEAD
中止 merge, 保持当前状态. (merge 途中无法执行 git commit --amend, 且存在未提交到 index 的修改)
git merge --quit
此时不会动位于 index 里面的内容.
自动从跟踪的远程分支中合并代码
git pull
相当于依次调用
git fetch <remote> <branch>
git merge remote/branch
其中, remote 和 branch 取自当前 branch 的跟踪信息. 如果 pull 中出现 fatal: refusing to merge unrelated histories 错误. 则加上选项 --allow-unrelated-histories 即可.
向远程跟踪分支中推送代码
git push <remote> <local_branch>:<remote_branch>
向远程仓库添加本地建立的新分支
git push -u <remote> <local_branch>:<remote_branch>
删除远程分支
git push <remote> :<remote_branch>
或
git push <remote> --delete <remote_branch>
删除远程 tag
git push <remote> --delete <remote_tag>
建立 git web 服务的工具: Gitweb
查看工作目录的修改
git diff
或
git difftool
提交修改
git commit [-a] [-m "msg"]
当 git merge 出现冲突时, 可用如下命令修正冲突
git mergetool
然后再用
git commit
提交合并结果
恢复到 merge 前的状态
git merge --abort
提交部分修改到 index
git add <file>
交互式选择提交每一处修改
git add -i
暂存当前的工作目录 (只保存针对当前 branch diff 的部分)
git stash push
取回暂存的工作目录并应用到当前 branch 上.
git stash pop
交换两个 parent 的顺序
git reset --hard $(git commit-tree -p HEAD^2 -p HEAD^1 -m "New commit message" "HEAD^{tree}")
打包当前 git repository (用于在网络环境不好时远程交换)
git bundle create <file>
设提交路径为 a1 -- a2 -- a3 -- a4 -- a5 -- a6, 若要删除提交 a2, a3, 则可用命令
git rebase --onto a1 a3 a6 或 git rebase --onto HEAD~5 HEAD~3 HEAD
[user]
name = Colin Teng
email = tfcolin@224488.com
[diff]
tool = vimdiff
[difftool]
prompt = true
[merge]
tool = vimdiff
[mergetool]
prompt = false
[alias]
d = difftool
[difftool "vimdiff"]
cmd = vimdiff "$LOCAL" "$REMOTE"
[core]
editor = nvim
[log]
decorate = full
本地配置文件位于: .git/config 全局配置文件位于: ~/.gitconfig
可以通过
git config [--local|--global] aaa.bbb <value|default>
来设置选项. 通过
git config [--local|--global] -l
来列出所有选项. (--local 表示针对当前 repository 的选项. --global 为全局选项)
可以在 git repository 目录中编辑 .gitignore 文件, 每行一个要忽略的文件 pattern, 相应文件就会在 git add 时被忽略.