Pro Git 2 阅读笔记

原书地址: http://git-scm.com/book/zh/v2

初始化一个 repo

1
2
3
4
git init // 将在目录下创建 .git
git add . // 添加目录下所有文件到 git 暂存区(Staging Area)
// 不要忘记 LICENSE 和 README.md
git commit -m "init a project" // 提交到本地 repo

克隆一个仓库 git clone

1
2
git clone https://example.com/username/repo
git clone https://example.com/username/repo rename // 将以 "rename" 存储

查看当前状态 git status

1
git status
  • Untracked 未跟踪的数据:文件在文件夹中,但不在仓库中
    • 是新增文件,将显示 new file: file.name 使用 git add 来添加它
    • 已经从 repo 中 git remove
  • Unmodified 未更改:一起都和看上去的一样
  • Modified 已更改:文件发生了变化
    • 将显示 modified: file.name 需要 git add 来暂存更改
  • Staged 已暂存:改动已经存储到暂存区

Staged 已为已经准备好将改动添加到下一次 commit 中,已暂存的将显示在 Changes to be committed: 中,未暂存的将被显示在 Changes not staged for commit: 中,一个文件可能同时在上面两个位置出现,因为在 staged 之后文件又发生了改动,如果此时 git commit,被提交的将会是最后一次运行 git add 时的版本,而非工作目录的版本。

git status -s // --short 将会更为简略的显示状态信息。

1
2
3
4
5
6
$ git status -s
M 已修改,未暂存
MM 已修改,已暂存,而后又被修改
A 新添加
M 已修改,已暂存
?? 未跟踪

忽略文件 .gitignore

使用 .gitignore,全局使用 .gitignore_global

查看更改 git diff

1
2
3
git diff // 查看未暂存的变更
git diff --cached // 查看已暂存的变更
git diff --staged // 与 -cached 相同

提交更改 git commit

1
2
3
4
5
6
git commit // 这种方式将会打开 .gitconfig 中定义的 "core.editor" 来编辑消息 \
并且默认将包含最后一次 "git status" 的内容
git commit -v // 打开的编辑器中还会有 diff 信息
// 上面两张方法中退出编辑器中,git 将会丢弃所有 `#` 开头的注释行
git commit -m "message" // 直接将消息写在 "message"
git commit -a // 把所有已经跟踪过的文件全部添加并提交,不需要再对已修改的内容 "git add"

修改提交信息 git commit --amend

1
2
3
git commit --amend -m "New Message"
// 如果已经之前已经推送到远程仓库,就需要强制推送:
git push <remote> <branch> --force // -f

移除文件 git rm

1
2
rm name.file // 从工作目录中删除某个文件
git rm name.file // 使 git 记录此次删除操作

如果在之前修改过文件并且已经暂存(git add),将需要使用 git rm -f name.file 来强制删除。

如果想从仓库中移除但在工作目录中保存文件(例如将编译产生的文件添加或者 .DS_Store 等):

1
2
3
4
git rm --cached out.a
// git 的 glob 模式
git rm log/\*.log // 删除 log/ 目录下 所有扩展名为 .log 的文件
git rm \*~ // 删除所有以 ~ 结尾的文件

移动文件 git mv

1
2
3
4
5
git mv file_form file_to // 文件将从 file_form 重命名为 file_to
// 效果类似下面这样
mv file_form file_to
git rm file_form
git add file_to

查看提交历史 git log

1
2
3
4
5
6
7
8
9
10
git log // 最详细的历史,从第一次开始,包括 SHA-1、作者、时间和消息
// 一些其它参数
git log -p // 用于显示每次提交间被修改的内容
git log -3 // 标识只显示最近三次提交的修改
git log --stat // 显示简略的统计信息(多少个文件被修改,新增多少行,删除多少行)
// 控制显示方式
git log --pretty=oneline // 全都在一行显示,还有 "short""full""fuller"
//高度自定义的显示方式,使用 "git log --pretty=format" 将显示帮助
git log --pretty=format:"%h - %an, %ar : %s" // 0354b3e - excited, 1 min ago : stay naive
git log --pretty=format:"%h - %an, %ar : %s" --graph // 加上 ASCII 字符串来形象的标识分支、合并历史

限制输出长度 --since--until

1
2
3
4
5
6
7
git log --since=7.weeks
git log --since="2 years 1 day 3 minutes ago"
git log --since="1889-05-35"
git log --author="Tuccuay" // 搜索指定作者的提交
git log --grep="fix" // 搜索所有信息中带 "fix" 的提交
git log --author="Tuccuay" --grep="fix" --all-match // 搜索同时满足两个要求的提交 \
(不加 "--all-match" 将会把只匹配一个条件的也显示出来)

撤销操作

1
2
git commit --amend // 会将暂存区中的文件合并到上一次的提交中,\
如果自上一次提交依赖没有做任何修改,那么只会修改提交信息

从暂存区中取消文件 git reset HEAD

1
git reset HEAD some.file // 从暂存区中取出 some.file

撤销修改 git checkout

1
2
3
git checkout -- DO_NOT_CHANGE_FILE // 这个文件将被回退到上一次提交时的样子
git checkout <SHA> // 退回到指定的 SHA 版本的状态
git checkout -b <SHA> // 如果需要提交修改,用 -b 来检出到一个新的分支

撤销最后一次代码提交

1
2
3
4
5
git reset --soft HEAD~1
# 这里进行修正
git add -A . // 添加文件
git commit -c ORIG_HEAD // 提交更改
git commit -C ORIG_HEAD // -C 则不修改之前的 commit message

远程仓库 git remote

1
2
git remote // 显示所有远程仓库的名称 (例如 "origin"
git remote -v // 同时也显示远程仓库的地址 "origin [email protected]:example/project.git"

添加远程仓库 git remote add name URI

1
git remote add origin [email protected]:example/project.git

从远程仓库拉取 git fetch

1
git fetch [remote-name] // 如果没有 remote-name,将会拉取默认的 origin

推送到远程仓库 git push

1
git push origin master // 将 master 分支 push 到 origin

重命名或者移除远程仓库 git remote rename / git remote rm

1
2
git remote rename oldName newName // 从 "oldName" 更名为 "newName"
git remote rm newName // 移除名为 "newName" 的远程仓库

打标签 tag

列出标签 git tag

1
2
3
4
git tag // 列出所有标签
git tag -l v1.* // 列出匹配的标签
git tag -l v1.0.0-* // 列出匹配的标签
git tag -l prefix*// 列出匹配的标签

附注标签(annotated) git tag -a

附注标签是一个存储在 repo 中的完整对象,包含作者,时间,邮件和信息,并且可以被 GPG 签名以验证。

1
git tag -a v0.1.3 -m 'Release v0.1.3'

轻量标签(lightweight) git tag

轻量标签不会改变分支,他只是引用 tag 的那一次 commit。

1
git tag v0.0.1-alpha-0001

在后期为过去的提交打标签 git tag -a [hash]

我们在提交的时候忘记了 tag,后面想起来也可以为以前的提交打标签。

1
2
3
4
5
6
git log --property=oneline // 先看看提交历史
52457732d2ec18fc98b7eb32833ad99d9920cdf8 fix typo
7f9712293fc0c9a7f124a1465d7913bbf00f6c95 release there version
11033567d8702731b68005ce69d9c852e271b56d merge PR#467
// 我们要为中间的那个 commit 打 tag
git tag -a v0.1.2 00f6c95

将标签推送到远程仓库(共享标签)git push

推送标签和推送分支一样

1
2
git push origin v0.1.6
git push origin --tags // 把所有标签都 push 到 origin

检出标签 git checkout -b [branchname] [tagname]

把 v2.0.0-beta-20029 检出到 develop 分支(因为 tag 并不像 branch 一样能够来回切换)

1
git checkout -b develop v2.0.0-beta-20029

git 别名 alias

1
2
3
4
5
6
7
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 config --global alias.unstage 'reset HEAD --' // 取消暂存
git config --global alias.last 'log -1 HEAD' // 查看最后一次提交
git config --global alias.visual '!gitk' // 甚至可以执行一些不是 git 里的命令

更多的别名参考这里: https://github.com/mathiasbynens/dotfiles/blob/master/.gitconfig

基础部分结束


阅读进度: 3.1 Git 分支 - 分支简介


1
2
3
git branch –delete –force // 删除分支
git branch -D
git push origin –delete // 删除远程分支