主要内容:【Git 协议与工作协同】、【冲突解决】、【Git 里程碑】、【Git 分支】、【远程版本库】、【补丁文件交互】
Git 协议与工作协同
Git 支持的协议
SSH、GIT、HTTP、HTTPS、FTP、FTPS、RSYNC 及前面已经看到的本地协议。
SSH 协议:
ssh://[user@]example.com[:port]/path/to/repo.git/ |
GIT 协议,最常用的只读协议:
git://example.com[:port]/path/to/repo.git/ |
HTTP[S] 协议:
http[s]://example.com[:port]/path/to/repo.git/ |
强制非快进式推送
git push -f |
强制推送,会强制刷新服务器中的版本。
禁止非快进式推送
git --git-dir=/path/to/repos/shared.git config receive.denyNonFastForwards true |
冲突解决
拉回操作中的合并
git pull = git fetch + git merge |
合并策略
Git 合并操作支持很多合并策略,默认会选择最适合的合并策略。例如,和一个分支进行合并时会选择 recursive 合并策略,当和两个或两个以上的其他分支进行合并时采用 octopus 合并策略。
git merge [-s <strategy>] [-X <strategy-option>] [<commit>...] |
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version.
git merge -s recursive -X ours [<commit>...] |
Merge branch obsolete into the current branch, using ours merge strategy:
git merge -s ours obsolete |
Git 里程碑
显示里程碑
git tag |
显示说明。-n<num>
显示最多 <num>
行里程碑的说明:
git tag -n1 |
使用统配:
git tag -l v1.* |
查看提交对应的里程碑及其他引用:
git log --oneline --decorate |
创建里程碑
当创建了里程碑 mytag 后,会在版本库的 .git/refs/tags 目录下创建一个新文件。实际上指向的是一个提交:
git tag mytag |
带说明的 tag 指向的不再是一个提交,而是一个 tag 对象:
git tag -m "My first annotated tag." mytag2 |
为里程碑对象添加 GnuPG 签名:
git tag -s -m "My first GPG-signed tag." mytag3 |
删除里程碑
git tag -d mytag |
共享里程碑
创建的里程碑,默认只在本地版本库中可见,不会因为对分支执行推送而将里程碑也推送到远程版本库。
将 mytag 里程碑共享到上游版本库:
git push origin mytag |
所有里程碑全部推送到远程版本库:
git push origin refs/tags/* |
- 里程碑共享,必须显式的推送。
- 执行获取或拉回操作,自动从远程版本库获取新里程碑,并在本地版本库中创建。
- 如果本地已有同名的里程碑,默认不会从上游同步里程碑,即使两者里程碑的指向是不同的。
删除远程版本库的里程碑
git push origin :mytag2 |
里程碑命名规范
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:
- 主版本号:当你做了不兼容的 API 修改,
- 次版本号:当你做了向下兼容的功能性新增,
- 修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译信息可以加到 主版本号.次版本号.修订号
的后面,作为延伸。
Git 分支
分支是代码管理的利器。如果没有有效的分支管理,代码管理就适应不了复杂的开发过程和项目的需要。
分支命令概述
# 显示 |
创建并切换到新分支:
git checkout -b <new_branch> [<start_point>] |
分支变基
- master
- dev(开发完成,领先 master)
# 先切换到 dev |
远程版本库
远程分支
查看远程分支:
git branch -r |
在向远程版本库执行获取操作时,不是把远程版本库的分支原封不动地复制到本地版本库的分支中,而是复制到另外的命名空间。
远程分支不是真正意义上的分支,是类似于里程碑一样的引用。如果针对远程分支执行检出命令,会看到大段的错误警告。
远程分支类似于里程碑,如果检出就会使得头指针 HEAD 处于分离头指针状态。实际上除了以 refs/heads 为前缀的引用之外,如果检出任何其他引用,都将使工作区处于分离头指针状态。如果对远程分支进行修改就需要创建新的本地分支。
分支追踪
为了能够在远程分支 origin/hello-1.x
上进行工作,需要基于该远程分支创建本地分支:
git checkout hello-1.x |
从远程分支创建本地分支,自动建立了分支间的跟踪,而从一个本地分支创建另外一个本地分支则没有。
从 hello-1.x
分支中创建新的本地分支 hello-jx
,并与远程建立联系。
git checkout -b hello-jx hello-1.x |
cat .git/config |
远程版本库
# 设置 |
PUSH 和 PULL 操作与远程版本库
在执行 git pull
操作的时候可以通过参数 --rebase
设置使用变基而非合并操作,将本地分支的改动变基到跟踪分支上。为了避免因为忘记使用 --rebase
参数导致分支的合并,可进行设置:
git config branch.<branchname>.rebase true |
这样在遇到冲突(本地和远程分支出现偏离)的情况下,会采用变基操作,而不是默认的合并操作。
如果为本地版本库设置参数 branch.autosetuprebase
,值为 true
,则在基于远程分支建立本地追踪分支时,会自动配置 branch.<branchname>.rebase
参数。
分支和里程碑的安全性
用
reflog
记录对分支的操作历史。默认创建的带工作区的版本库都会包含core.logallrefupdates
为true
的配置,这样在版本库中建立的每个分支都会创建对应的reflog
。但是创建的裸版本库默认不包含这个设置,也就不会为每个分支设置reflog
。可能因为分支误操作导致数据丢失,可以考虑为裸版本库添加此配置。关闭非快进式提交。配置
receive.denyNonFastForwards
设置为true
,则禁止一切非快进式推送。更好的方法是通过架设基于 SSH 协议的 Git 服务器,配置强制提交的用户权限。关闭分支删除功能。配置
receive.denyDeletes
设置为true
,则禁止删除分支。更好的方法是:配置分支删除的用户权限。
补丁文件交互
将最近三个提交转换为补丁文件:
git format-patch -s HEAD~3..HEAD |
-s
会在导出的补丁文件中添加当前用户的签名。
应用补丁:
git am user1-mail-archive |
git apply
可以应用一般格式的补丁文件,但是不能执行提交,也不能保持补丁中的作者信息。