2. Git 基础
git status
git status
:查看当前状态git status -s
:简化输出
1 | $ git status |
.gitignore
可以使用 glob
模式匹配。
1 | # 忽略所有前缀长度 >= 2 的 .a 文件,例如忽略 foo.a 但不忽略 p.a |
git diff
git diff
:比较工作和暂存git diff --staged
:比较暂存和最新提交
git commit
git commit -a
:自动将已跟踪文件 update- 不等于
git add -A
- 不等于
git rm
git rm <file>
:也会移除工作区文件- 用
--cached
避免
- 用
git mv <old_file> <new_file>
git log
-p -2
:显示最近两次提交的差异--pretty=online
:单行显示--graph
:显示分支的树形图
2.4 撤销操作
git commit --amend
:修补最后一次提交git reset HEAD <file>
:撤销文件的暂存git checkout -- <file>
:撤销文件的修改(危险)
2.5 远程仓库的使用
git remote -v
:查看远程仓库名称和 urlgit remote add <shortname> <url>
:添加远程仓库git remote show <remote>
:查看远程仓库的更多信息rename/remove
git fetch <remote>
:从远程仓库拉取数据git push <remote> <branch>
:推送数据到远程仓库
2.6 打标签
查询:
git tag
:列出标签-l "v1.8.5*"
:列出所有符合模式的标签
git show <tagname>
:查看标签信息
创建:
git tag -a <tagname> -m "my version 1.4"
:创建附注标签git tag <tagname>
:创建轻量标签git tag -a <tagname> 9fceb02
:补办标签
删除:
git tag -d <tagname>
:删除标签
标签不会在 git push
时自动推送,必须手动推送标签:
- 添加:
git push origin <tagname>
或git push origin --tags
- 删除:
git push origin --delete <tagname>
2.7 Git 别名
git config --global alias.unstage 'reset HEAD --'
git unstage <file>
:等价于git reset HEAD -- <file>
git config --global alias.visual '!echo hello'
git visual
:等价于echo hello
3. Git 分支
3.1 分支简介
Git 储存三种对象:
commit
:储存 commit 信息,指向对应快照的tree
根节点tree
:储存路径树结构blob
:储存文件
HEAD
指向当前所在分支。
- 创建:
git branch <newbranch>
- 删除:
git branch -d <branch>
- 切换:
git checkout <branch>
也可以用 git checkout -b <newbranch>
直接创建并切换。
3.2 分支的新建与合并
git merge <branch>
:HEAD = merge(HEAD, branch)
--no-ff
:禁用快进合并
快进:若 HEAD
是 branch
的祖先,则可以直接跳到 branch
,称为快进。
如果出现冲突,需要手动去对应文件里修改,再用 git add
和 git commit
。
1 | <<<<<< HEAD:index.html |
3.6 变基
1 | git checkout experiment |
变基:提取当前分支(experiment
)中到最近公共祖先引入的修改,然后在目标分支(master
)上重新应用,并修改当前分支的提交。(即 HEAD' = branch + (HEAD - LCA)
)
整合结果相同,但历史更加简洁。
进阶:
git rebase --onto master server client
,将client
减去server
的修改应用到master
上。git rebase master server
,将server
的修改应用到master
上。
变基前:
变基后:
风险:如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。——也就是说,只在本地分支上使用变基。
Figure 47. 你将相同的内容又合并了一次,生成了一个新的提交
高级魔法:用 git rebase teamone/master
可以实现智能变基合并(丢弃 C4 和 C6)。
合并和变基的区别:
至此,你已在实战中学习了变基和合并的用法,你一定会想问,到底哪种方式更好。 在回答这个问题之前,让我们退后一步,想讨论一下提交历史到底意味着什么。
有一种观点认为,仓库的提交历史即是 记录实际发生过什么。 它是针对历史的文档,本身就有价值,不能乱改。 从这个角度看来,改变提交历史是一种亵渎,你使用 谎言 掩盖了实际发生过的事情。 如果由合并产生的提交历史是一团糟怎么办? 既然事实就是如此,那么这些痕迹就应该被保留下来,让后人能够查阅。
另一种观点则正好相反,他们认为提交历史是 项目过程中发生的事。 没人会出版一本书的第一版草稿,软件维护手册也是需要反复修订才能方便使用。 持这一观点的人会使用 rebase 及 filter-branch 等工具来编写故事,怎么方便后来的读者就怎么写。
总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。