Git
分布式版本控制系统,区别于SVN等集中式版本控制系统。
版本库、工作区、暂存区
版本库(repository)
repo中所有文件都可以被git管理,修改、删除都可以被git跟踪、还原。Git跟踪的是修改而不是文件。
创建repo
1 | mkdir <dir name> |
可建立一个空repo,当前目录多了.git
的目录,是Git用来跟踪管理版本库的,可用ls -ah
来查看。
把文件添加至repo
版本控制系统只能跟踪文本文件的改动(如txt,网页,代码文件等),图片、视频(还有word)这类二进制文件,只能知道大小变化。建议使用标准等UTF-8编码。
1 | git add <file> |
git add
将文件添加至repo,而git commit
可以作一个提交。-m
后面输入的是本次提交的说明,比如git commit -m "add 3 files."
。git add
可以反复多次使用添加多个文件,实际上就是把文件修改添加到暂存区,然后用git commit
完成提交到当前分支。
.git目录
Working Directory有一个隐藏目录.git
,里面即是Git的版本库。其中最重要的就是Stage(暂存区),以及Git自动创建的第一个分支master
和指向master
的指针HEAD
。
工作区(working directory)&暂存区(stage/index)
工作区是能直接查看到文件的区域。
暂存区就是缓存文件修改的区域,位于repo中。
时光机穿梭和版本回退
git status
命令可以查看工作区的状态:是否被修改过(但还没有提交)。
git diff
命令查看被修改的内容/difference,显示的格式是Unix通用的diff格式。git diff HEAD -- <file>
可以查看工作区和版本库里最新版本的区别。
git log
命令查看版本控制系统中,版本修改的历史记录。加上--pretty=oneline
参数可以简化显示。
注:
commit id
(版本号)是SHA1计算出的十六进制数字,不同于SVN递增的版本号,Git用大串数字满足分布式的需求。
git reflog
命令用来记录Git的每一次提交(的commit id)。
git reset
git reset --hard <commit id>
即可回退到版本号对应的版本。其中commit id可以只打前面若干个数字(如果能唯一确定某个版本的话)。还可以用HEAD
来回溯最近的版本。
git reset HEAD <file>
可以把暂存区的修改撤销掉(unstage),将其修改重新放回工作区。
1 | HEAD #当前版本 |
git check
git check -- <file>
命令可以把工作区的修改(包括删除)全部撤销。包含两种情况:
-
文件自修改后还没有放到暂存区,则撤销后和版本库一模一样;
-
文件已经添加到暂存区,又作了修改,则撤销后和添加到暂存区时一样。
总之是让文件回到最近一次git add
或者 git commit
的状态。
git rm <file>
命令可以删除(或者说是修改)版本库的文件,然后执行git commit
完成删除。(先删文件后,git rm <file>
和git add <file>
是一样的)
分支管理
分支管理示意
- 一开始仅有master一条分支,指针
master
指向最新的提交,而HEAD
指向master
;

- 当创建一个新分支
dev
时,新指针dev
被创建并指向master
相同的提交,而HEAD
指向dev
表示当前分支在dev
上;

- 之后工作区的提交则是
dev
分支;

- 如果
dev
分支上的工作完成了,想合并dev
和master
分支,只需要把master
指针指向dev
分支的当前提交。合并完成后删除dev
指针,就只剩下master
分支了。

分支创建、切换和删除
1 | git branch <branch name> # 创建某个branch |
git branch
命令可以查看当前分支。它会列出所有分支,并在当前分支前标记*
号。
git merge
命令用于合并指定分支到当前分支。比如当前在master
分支,且要合并dev
分支,那么使用命令为git merge dev
即可。
【推荐】最新版本的Git使用git switch
来切换分支。
1 | git switch -c <branch name> # 创建并切换到新的分支 |
git branch -d <branch name>
命令可以删除某个分支。
冲突
当Git无法自动合并分支时,就要首先解决冲突,再提交进行合并。解决冲突当方法就是把造成合并失败的文件手动编辑为希望的内容再提交。git log --graph
可以看到分支合并图。
通常合并分支会用Fast forward
模式,但这种模式下删除分支后会丢掉分支信息。如果强制禁用该模式,那么merge时会生成一个新的commit,这样就可以从分支历史上看到分支信息。
1 | git merge --no-ff -m <message> <branch name> |
其效果如图:

分支策略
实际开发中应按照几个基本原则进行分支管理:
-
首先
master
分支应该是非常稳定的,仅用来发布新版本; -
在其他分支修改、提交,到某个时候再合并到
master
分支上;
Bug 分支
假设需要修复dev
分支上一个代号为101的bug,会想创建一个issue-101
分支来修复它,但此时dev
分支上进行中的工作还没有提交。那么可以用stash
功能,将当前工作区现场保存,等修复完成后恢复现场继续工作。如:
1 | git stash |
注意:修复哪个分支,就在哪个分支上创建临时分支。
git stash list
命令查看保存了的现场。
git stash apply
命令恢复现场,但是stash内容并不删除,需要用git stash drop
来删除。也可以用git stash pop
恢复现场的同时也把stash内容删了。可以多次stash,恢复的时候先用git stash list
查看,然后恢复到指定的stash,用git stash apply stash@{<number>}
。
对于多个有同个bug的分支,可以用cherry-pick
命令,复制特定的一个提交(这个例子里是issue-101
)到当前分支,比如:
1 | git branch |
注意到这里两个分支下commit id不相同,因为尽管它们改动相同,但确实是两个不同的commit。
Feature 分支
假设工程需要添加一个新feature,最好新建一个feature分支,在上面开发。
如果没有合并就需要去掉该feature,使用命令删除:
1 | git branch -d <branch name> # 删除分支 |
多人协作
查看远程库的信息
1 | git remote |
推送分支
推送分支就是把该分支上的所有提交推送到远程库,推送时要指定本地分支,如:
1 | git push origin master |
但是并非所有本地分支都需要远程推送:
-
master
分支是主分支,因此要时刻与远程同步; -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要远程同步; -
bug
分支只用于本地修复bug,就没必要推送远程; -
feature
分支是否推送取决于是否团队合作开发feature。
抓取分支
多人协作时团队各成员会在master
和dev
分支上推送各自的修改。但clone默认情况下只能看到本地的master
分支。如果要在dev
分支上开发,就必须创建远程origin的dev
分支到本地。
1 | git checkout -b dev origin/dev |
异步修改后直接git push
很可能会失败,这时先用git pull
把最新的提交从origin/dev
上抓下来,然后在本地合并解决冲突,再做推送。如果git pull
也失败了,可能是因为没指定本地dev
分支与远程origin/dev
分支的链接:
1 | git branch --set-upstream-to=origin/dev dev |
之后git pull
,确保没有冲突后合并后再git push
。
rebase
rebase操作(git rebase
)可以通过修改本地分叉提交的方式将分叉整合成一条直线,看上去更直观。
标签管理
tag可以和commit绑在一起,相比commit id,tag更容易被记住。创建的标签都只存储在本地,不会自动推动到远程库。
创建标签
1 | git branch |
标签不是按时间顺序列出的,而是按字母排序的,可用git show <tagname>
查看标签信息。
1 | git tag -a <tag name> -m <message> <commit id> |
操作标签
git tag -d <tag name>
命令删除标签。
git push origin <tag name>
命令推送某个标签到远程库。
git push origin --tags
命令一次性推送全部尚未推送到远程库的本地标签。
git push origin :refs/tags/<tag name>
命令删除远程库中的标签。
GitHub
(optional) ssh-ketgen -t rsa -C "email@example.com"
生成密钥对。在GitHub上 ADD SSH Key,将id_rsa.pub
的内容复制到Key文本框内。
关联远程仓库
1 | git remote add origin git@github.com:XXX.git |
origin
是Git远程库的默认叫法,也可以改成别的(不推荐)。
将本地 master 分支的最新修改推送至GitHub,使用命令:
1 | git push origin masteror |
git clone
命令支持ssh 和 https等多种协议;
-
在GitHub上,可以任意fork开源仓库;
-
自己拥有fork后的仓库的读写权限;
-
可以推送pull request给官方仓库贡献代码。
例子:Hexo
Install tools for Hexo
可以通过以下命令查看是否安装成功;
1 | git --version |
Create a Github repo
项目必须要遵守格式:账户名.github.io,不然接下来会有很多麻烦。并且需要勾选Initialize this repository with a README.
访问 name.github.io 可以检查是否创建成功;
Install Hexo
执行 npm install hexo -g
安装Hexo。用 hexo -v
查看是否成功;再用 hexo init
初始化该文件夹。(看到“Start blogging with Hexo!”一般就成功了,不放心可以注意下打印信息)
输入npm install
安装所需组件。
hexo g
生成,可以用 hexo s
开启本地服务器,访问对应网址就可以检查blog的状态了。(如果端口被占用可用 hexo server -p [your port]
来改变端口号)
Configure Github repo
1 | 配置github账号和邮箱信息 |
之后在GitHub账户上的SSH and GPG keys中添加ssh key,将id_rsa.pub文件中的内容复制上去。
输入 ssh -T git@github.com
测试添加ssh是否成功。
最后配置blog文件夹里的 _config.yml
文件末尾处。
1 | # Deployment |
Test
新建一篇博文 hexo new post "blah blah"
安装一个扩展 npm install hexo-deployer-git --save
生成并部署到主页 hexo d -g
,访问https://name.github.io查看。