Git配置
相关文件
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
/etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行 git config 时带上 –system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 你可以传递 –global 选项让 Git 读写此文件,这会对你系统上所有的仓库生效。
当前使用仓库的 Git 目录中的 config 文件(即 .git/config ):针对该仓库。 你可以传递 –local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。 (当然,你需要进入某个 Git 仓库中才能让该选项生效。)
相关命令
1 2 3 4
| git config --list [--show-origin] git config --[local/global/system] --list git config key [value] git config --unset key
|
配置参考
帮助文档
1 2 3 4 5
| git help <verb> git <verb> --help man git-<verb> git <verb> -h
|
基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
git init
git clone [--recurse-submodules] <url> [<rep_name>] git clone [--recurse-submodules] ssh://user@server:path/to/repo.git
git status [-s|--short] git log
git add <file>... git add [-p|--patch]
git commit [-m "message"] git commit -a -m "message"
git describe <branch> git archive <branch> --prefix='dir/'
git ls-files git ls-files files...
git rm --cached files... git rm --cached -r dirs... git rm files...
git push <remote> <localbranch>:<remotebranch> git pull <remote> <remotebranch>:<localbranch>
git mv file_from file_to
git fetch <remote>
git merge <branchname>
git ls-remote <remote> git push <remote> --delete <remotebranch>
|
.gitignore
格式规范:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 取消忽略指定模式的文件或目录,可以在模式前加上叹号(
!)取反。
glob 模式:
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
- 星号(*)匹配零个或多个任意字符;
- [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
- 问号(?)只 匹配一个任意字符;
- 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配 (比如 [0-9] 表示匹配所有 0 到 9 的数字)。
- 使用两个星号表示匹配任意中间目录,比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等。
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12
| # 忽略所有的 .a 文件 *.a # 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件 !lib.a # 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO /TODO # 忽略任何目录下名为 build 的文件夹 build/ # 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt doc/*.txt # 忽略 doc/ 目录及其所有子目录下的 .pdf 文件 doc/**/*.pdf
|
在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore 文件,它递归地应用到整个仓库中。 然而,子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。
git diff
1 2 3 4 5 6 7 8
| git diff [<file>...] git diff --[staged|cached] <file>...
git diff --check
git diff branch1...branch2
git difftool --tool-help
|
git reflog
当你在工作时,Git 会在后台保存一个引用日志(reflog),引用日志记录了最近几个月你的 HEAD 和分支引用所指向的历史。
每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。
引用日志只存在于本地仓库,它只是一个记录你在自己仓库里做过什么的日志。其他人拷贝的仓库里的引用日志不会和你的相同,而你新克隆一个仓库时,引用日志是空的。
git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| git log git log -p [-n] git log --stat git log --pretty=oneline git log --pretty=format:"%h - %an, %ar :%s" git log --graph git log --decorate
git log --since=2.weeks git log -S string
git log --abbrev-commit
git log branch1..branch2 git log --left-right branch1...branch2
|
贮藏
1 2 3 4 5 6
| git stash [-u] [--patch] [push] git stash list git stash apply stash@{n} git stash drop stash@{n} git stash pop stash@{n} git stash branch <new branchname>
|
搜索
Git 调试
1 2 3 4 5 6
| git blame [-L n1,n2] <file>
git bisect start git bisect bad git bisect good <commit> git bisect reset
|
子模块
1 2 3
| git submodule add <url> git submodule init git submodule update
|
reset揭秘
reset 移动 HEAD 指向的分支指针
1
| git reset --[soft|mixed|hard] <SHA-1> <file...>
|
|
HEAD |
Index |
Workdir |
| commit level |
|
|
|
| reset –soft [commit] |
REF |
NO |
NO |
| reset [commit] |
ref |
yes |
no |
| reset –hard [commit] |
REF |
yes |
yes |
| checkout [commit] |
head |
yes |
yes |
| file level |
|
|
|
| reset [commit] |
no |
yes |
no |
| checkout [commit] |
no |
yes |
yes |
撤销操作
1 2 3
| git commit --amend [--no-edit] git restore --staged <file>... git restore <file>...
|
git remote
1 2 3 4 5 6 7
| git remote [-v] git remote show <remote>
git remote add <shortname> <url>
git remote rename <fromname> <toname> git remote remove <shortname>
|
git tag
Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)
- 轻量标签像一个不会改变的分支——它只是某个特定提交的引用。
- 附注标签是存储在 Git 数据库中的一个完整对象,它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间,此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG) 签名并验证.
默认情况下,git push 命令并不会传送标签到远程仓库服务器上。在创建完标签后你必须显式的推送标签到共享服务器上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| git tag [-l] git tag -l "tagname" git show <tagname>
git tag -a <tagname> -m <message> git tag <tagname>
git tag -a <tagname> <SHA>
git push <remote> <tagname> git push <remote> --tags
git tag -d <tagname> git push <remote> :refs/tags/<tagname> git push <remote> --delete <tagname> git checkout <tagname>
|
Git别名
1 2
| git config --global alias.<name> '<internalcommand>' git config --global alias.<name> '!<externalcommand>'
|
分支管理
分支模型
一个文件对应于一个blob对象
整个项目对应着一个树对象(snapshot)
一次提交对应着一个对象

HEAD指针是指向当前所在本地分支的指针
本地分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| git branch git branch -a git branch -r git branch -v
git branch <branchname> git checkout <branchname> git checkout -b <newbranchname> git checkout -b <branch> <tagname> git branch -d <branch> git branch -D <branch>
git branch --merged git branch --no-merged git branch --no-merged <branch>
|
当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。
在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。
如果你对结果感到满意,并且确定之前有冲突的的文件都已经暂存了,这时你可以输入 git commit 来完成合并提交。
远程分支
远程跟踪分支是远程分支状态的引用。它们是你无法移动的本地引用。一旦你进行了网络通信, Git 就会为你移动它们以精确反映远程仓库的状态。请将它们看做书签, 这样可以提醒你该分支在远程仓库中的位置就是你最后一次连接到它们的位置。
1 2 3 4 5 6 7 8 9 10
| git ls-remote <remote> git remote show <remote>
git fetch <remote> git push <remote> <localbranch>:<remotebranch>
git checkout -b <branch> <remote>/<remotebranch>
git fetch --all git push <remote> --delete <remotebranch>
|
跟踪分支
从一个远程跟踪分支检出一个本地分支会自动创建所谓的“跟踪分支”(它跟踪的分支叫做“上游分支”)。
跟踪分支是与远程分支有直接关系的本地分支。如果在一个跟踪分支上输入 git pull ,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。
当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支。
当设置好跟踪分支后,可以通过简写 @{upstream} 或 @{u} 来引用它的上游分支。
1 2 3
| git checkout --track <remote>/<branch> git branch -u <remote>/<remotebranch> git branch -vv
|
变基
变基使得提交历史更加整洁。
你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的,但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。
1 2 3
| git rebase <branch> git rebase --onto <branch1> <branch2> <branch3> git rebase <branch1> <branch2>
|
如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基
Git原理
description 文件仅供 GitWeb 程序使用
logs 目录包含引用日志
config 文件包含项目特有的配置选项
info 目录包含一个全局性排除文件,用以放置那些不希望被记录在 .gitignore 文件中的忽略模式
hooks 目录包含客户端或服务端的钩子脚本
objects 目录存储所有数据内容
refs 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针
HEAD 文件指向目前被检出的分支
index 文件保存暂存区信息
Git对象
Git 的核心部分是一个简单的键值对数据库(key-value data store)。你可以向 Git 仓库中插入任意类型的内容,它会返回一个唯一的键,通过该键可以在任意时刻再次取回该内容。
一旦你将内容存储在了对象数据库中,那么可以通过 cat-file 命令从 Git 那里取回数据。
本文参考自Pro Git第二版.