Git基础
获取 Git 仓库
-
初始化仓库
$ git init
-
克隆仓库
git clone <url>
克隆 Git 的链接库 libgit2:
$ git clone https://github.com/libgit2/libgit2
在克隆远程仓库的时候,自定义本地仓库的名字为mylibgit:
$ git clone https://github.com/libgit2/libgit2 mylibgit
-
检查当前文件状态
$ git status
在 Untracked files下是新建的文件,即未跟踪的文件
在 Changes to be committed下面的,就说明是已暂存状态
在 Changes not staged for commit下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 -
跟踪新文件
git add命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。
跟踪 README文件:
$ git add READM
-
暂存已修改的文件
运行了 gitadd之后又作了修订的文件,需要重新运行 git add把最新版本重新暂存起来。
-
状态简览
git status -s命令或 git status --short命令,输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。新添加的未跟踪文件前面有 ??标记,新添加到暂存区中的文件前面有 A标记,修改过的文件前面有 M标记。
$ git status -s
-
忽略文件
创建一个名为 .gitignore的文件,列出要忽略的文件的模式。子目录中的 .gitignore文件中的规则只作用于它所在的目录中。
- 文件 .gitignore 的格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
- 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
- 星号(*)匹配零个或多个任意字符;
- [abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
- 问号(?)只匹配一个任意字符;
- 如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
使用两个星号(**)表示匹配任意中间目录
,比如 a/**/z 可以匹配 a/z 、 a/b/z 或a/b/c/z 等。
看一个 .gitignore 文件的例子:
# 忽略所有的 .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 的格式规范如下:
-
查看已暂存和未暂存的修改
比较工作目录中当前文件和暂存区域快照之间的差异
$ git diff
比对已暂存文件与最后一次提交的文件差异
$ git diff --staged # --staged 和 --cached 是同义词 $ git diff --cached
-
提交更新
运行提交命令git commit会启动你选择的文本编辑器来输入提交说明。退出编辑器时,Git 会丢弃注释行,用你输入的提交说明生成一次提交。启动的编辑器是通过 Shell 的环境变量 EDITOR 指定的,一般为 vim 或 emacs。使用 git config --global core.editor 命令可以自定义编辑器。
$ git commit
在 commit 命令后添加 -m 选项,将提交信息与命令放在同一行,如下所示:
$ git commit -m "Story 182: Fix benchmarks for speed"
-
跳过使用暂存区域
只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存
起来一并提交,从而跳过 git add 步骤。$ git commit -a -m ‘added new benchmarks’
-
移除文件
-
用 git rm 命令从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。会连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
-
要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f。
-
想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。
$ git rm --cached README
-
删除 log/ 目录下扩展名为 .log 的所有文件。
$ git rm log/\*.log
-
删除所有名字以 ~ 结尾的文件
$ git rm \*~
-
-
移动文件
在 Git 中对文件改名
$ git mv README.md README
-
查看提交历史
不传入任何参数的默认情况下,git log 会按时间先后顺序列出所有的提交,最近的更新排在最上面。选项 -p 或 --patch 会显示每次提交所引入的差异(按 补丁 的格式输出)。 也可以限制显示的日志条目数量,例如使用 -2 选项来只显示最近的两次提交:
$ git log -p -2
使用 --stat 选项查看每次提交的简略统计信息:
$ git log --stat
选项 --pretty可以使用不同于默认格式的方式展示提交历史。 这个选项有一些内建的子选项,比如 oneline 会将每个提交放在一行显示,还有 short,full 和 fuller 选项,它们展示信息的格式基本一致,但是详尽程度不一。format 可以定制记录的显示格式。
$ git log --pretty=oneline
$ git log --pretty=format:"%h - %an, %ar : %s"
git log --pretty=format 常用的选项
选项 | 说明 |
---|---|
%H | 提交的完整哈希值 |
%h | 提交的简写哈希值 |
%T | 树的完整哈希值 |
%t | 树的简写哈希值 |
%P | 父提交的完整哈希值 |
%p | 父提交的简写哈希值 |
%an | 作者名字 |
%ae | 作者的电子邮件地址 |
%ad | 作者修订日期(可以用 --date=选项 来定制格式) |
%ar | 作者修订日期,按多久以前的方式显示 |
%cn | 提交者的名字 |
%ce | 提交者的电子邮件地址 |
%cd | 提交日期 |
%cr | 提交日期(距今多长时间) |
%s | 提交说明 |
子选项oneline 或 format 与另一个 log 选项 --graph 结合使用可以形象地展示分支、合并历史。
$ git log --pretty=format:"%h %s" --graph
git log 的常用选项
选项 | 说明 |
---|---|
-p | 按补丁格式显示每个提交引入的差异。 |
–stat | 显示每次提交的文件修改统计信息。 |
–shortstat | 只显示 --stat 中最后的行数修改添加移除统计。 |
–name-only | 仅在提交信息后显示已修改的文件清单。 |
–name-status | 显示新增、修改、删除的文件清单。 |
–abbrev-commit | 仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
–relative-date | 使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
–graph | 在日志旁以 ASCII 图形显示分支与合并历史。 |
–pretty | 使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和format(用来定义自己的格式)。 |
–oneline | –pretty=oneline --abbrev-commit 合用的简写。 |
-
限制输出长度
使用 - 的选项,表示仅显示最近的 n 条提交,其中的 n 可以是任何整数。实践中这个选项不是很常用,因为 Git 默认会将所有的输出传送到分页程序中,所以一次只会看到一页的内容。选项 --since 和 --until 按照时间作限制。
例如,下面的命令会列出最近两周的所有提交:
$ git log --since=2.weeks
用 --author 选项显示指定作者的提交,用 --grep 选项搜索提交说明中的关键字。可以指定多个 --author 和 --grep 搜索条件,这样会只输出 任意 匹配 --author 模式和–grep 模式的提交。然而,如果添加了 --all-match 选项, 则只会输出 所有 匹配–grep 模式的提交。
接受一个字符串参数,并且只会显示那些添加或删除了该字符串的提交
$ git log -S function_name
选项路径(path)只显示某些文件或者目录的历史提交,path放在最后位置上,用两个短划线(–)隔开之前的选项和后面限定的路径名。
为了避免显示的合并提交弄乱历史记录,可以为 log 加上 --no-merges 选项。
限制 git log 输出的选项
选项 | 说明 |
---|---|
- | 仅显示最近的 n 条提交。 |
–since, --after | 仅显示指定时间之后的提交。 |
–until, --before | 仅显示指定时间之前的提交。 |
–author | 仅显示作者匹配指定字符串的提交。 |
–committer | 仅显示提交者匹配指定字符串的提交。 |
–grep | 仅显示提交说明中包含指定字符串的提交。 |
-S | 仅显示添加或删除内容匹配指定字符串的提交。 |
在 Git 源码库中查看 Junio Hamano 在 2008 年 10 月其间, 除了合并提交之外的哪一个提交修改了测试文件:
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
-
撤消操作
运行带有 --amend 选项的提交命令来重新提交:$ git commit --amend
这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。文本编辑器启动后,可以看到之前的提交信息。 编辑后保存会覆盖原来的提交信息。
例如,提交后发现忘记了暂存某些需要的修改,可以像下面这样操作: $ git commit -m 'initial commit' $ git add forgotten_file $ git commit --amend
-
取消暂存的文件
取消暂存文件,使用
git reset HEAD <file>
。取消暂存 CONTRIBUTING.md 文件:
$ git reset HEAD CONTRIBUTING.md
-
撤消对文件的修改
用最近提交的版本覆盖掉本地的修改:
git checkout -- <file>
$ git checkout – CONTRIBUTING.md
远程仓库的使用
-
查看远程仓库
查看已经配置的远程仓库服务器,运行 git remote 命令。指定选项 -v,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
$ git remote -v
-
添加远程仓库
运行 git remote add 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写
-
从远程仓库中抓取与拉取
从远程仓库中获得数据,可以执行:
$ git fetch <remote>
。用 git pull 命令来自动抓取后合并该远程分支到当前分支。 -
推送到远程仓库
备份到服务器:
git push <remote> <branch>
。将 master 分支推送到 origin 服务器:
$ git push origin master
-
查看某个远程仓库
查看某一个远程仓库的更多信息,使用
git remote show <remote>
命令。 -
远程仓库的重命名与移除
运行 git remote rename 来修改一个远程仓库的简写名。同样也会修改你所有远程跟踪的分支名字。
例如,想要将 pb 重命名为 paul,可以用git remote rename 这样做:$ git remote rename pb paul
使用 git remote remove 或 git remote rm 移除一个远程仓库,和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。例如:
$ git remote remove paul
打标签
-
列出标签
在 Git 中列出已有的标签只需要输入 git tag (可带上可选的 -l 选项 --list):
$ git tag
按照通配符列出标签需要 -l 或 --list 选项。
例如,Git 自身的源代码仓库包含标签的数量超过 500 个。 如果只对 1.8.5系列感兴趣,可以运行:
$ git tag -l "v1.8.5*"
-
创建标签
Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。
在 Git 中创建附注标签是在运行 tag 命令时指定 -a 选项。-m 选项指定了一条将会存储在标签中的信息。 如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息。$ git tag -a v1.4 -m "my version 1.4"
使用 git show 命令可以看到标签信息和与之对应的提交信息:
$ git show v1.4
-
轻量标签
轻量标签没有保存任何其他信息,不需要使用 -a、-s 或 -m 选项,只需要提供标签名字:
$ git tag v1.4-lw
-
后期打标签
要在之前的提交上补打标签,需要在命令的末尾指定提交的校验和(或部分校验和):
$ git tag -a v1.2 9fceb02
-
共享标签
创建完标签后必须显式地推送标签到共享服务器上,运行
git push origin <tagname>
。$ git push origin v1.5
想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。使用
git push <remote> --tags
推送标签并不会区分轻量标签和附注标签。$ git push origin --tags
-
删除标签
①删除掉你本地仓库上的标签,可以使用命令
git tag -d <tagname>
。例如,可以使用以下命令删除一个轻量标签:
$ git tag -d v1.4-lw
用
git push <remote>:refs/tags/<tagname>
来更新你的远程仓库,将冒号前面的空值推送到远程标签名,从而高效地删除它:$ git push origin :refs/tags/v1.4-lw
②直观的删除远程标签的方式:
$ git push origin --delete <tagname>
-
检出标签
查看某个标签所指向的文件版本,可以使用 git checkout 命令,这会使仓库处于“分离头指针(detached HEAD)”的状态。在“分离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。
因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:
$ git checkout -b version2 v2.0.0
在这之后又进行了一次提交,version2 分支就会因为这个改动向前移动, 此时它就会和 v2.0.0 标签稍微有些不同,这时就要当心了。
Git 别名
通过 gitconfig 文件来轻松地为每一个命令设置一个别名。
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
这意味着,当要输入 git commit 时,只需要输入 git ci。
取消暂存文件的暂存别名:
$ git config --global alias.unstage 'reset HEAD --'
等价于下面两个命令:
$ git unstage fileA
$ git reset HEAD -- fileA
想要执行外部命令,而不是一个 Git 子命令的话,可以在命令前面加入 ! 符号。
例如将 git visual 定义为 gitk 的别名:
$ git config --global alias.visual '!gitk'