1. 起步
1.1 版本控制
Git本质是一个分布式版本控制系统(Distributed Version Control System). 客户端可以完成的Clone整个仓库,然后进行修改和提交。这个好处是任何一个仓库出现问题都有其他的镜像来进行回复。每次提取操作都是对仓库的完备备份。
1.2 Git 简史
早起的Linux开发者使用的是一个叫做BitKeeper的工具来进行代码维护和管理。
但是2005年BitKeeper和Linux开源社区的合作关系结束,收回了BitKeeper的使用权利,让Linux开源社区受到重大影响,所以为了防止类似情况,天才们开发了Git,并且制定了一定的规范和功能标准。
1.3 Git 基础
Git的本质思想其实是,直接记录快照而不是差异比较。也就是说git只关心文件数据的整体是否发生变化。也就是Git把整个项目看做是一个完整的文件系统或者说是包,只有当这个整体发生变化的时候,git才会进行整体的cover或者clone等操作。具体思维如下图。
GIT思想在之后的功能介绍中我们会慢慢发现这个思路所带来的无与伦比的优势。
因为这个思路,git上的几乎所有操作都是本地执行。基本除了推送和拉取以外的其他所有版本操作都是离线完成,也就是我们可以在任何离线的平台上进行相应的版本管理,只要在未来连接网络的时候整体推送手头这个版本就可以。
同样因为这个思路,git可以时刻保证数据的完整性。因为git把整个Repo看做成一个整体,任何时候git只要算出本地文件整体的SHA-1哈希值,就可以确认文件的异同。而所有的git工作也就是依赖于这类指纹子串。这个好处是差异验证和文件系统结构内容的分离。
再次,得益于这个思路,git任何时候的操作仅仅是把数据添加到数据库而已,只要有定时的推送和拉取,根本无所谓数据丢失不丢。
在Git内部,文件只有三种状态,Comm###ified、Staged。Committed标识已经被安全保存在了本地数据库中,Modified标识修改了某个文件,Staged标识已经把改好的文件放在下次提交保存的清单中。
image.png简单来说就是如图所示。
每一个项目都有一个Git目录,如果是Clone获得的话,那么就是文件夹里面的./.git文件夹。如果是git clone —bare
获得的话,目录就是这个文件夹本身。
- 基本的 Git 工作流程如下:
- 在工作目录中修改某些文件。
- 对修改后的文件进行快照,然后保存到暂存区域。
- 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
1.4 安装 Git
源代码安装:
首先安装相关的依赖包
$ yum install curl-devel expat-devel gettext-devel \ openssl-devel zlib-devel
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \ libz-dev libssl-dev
之后从官网安装对应的源码包
然后编译并安装
$ tar -zxf git-1.7.2.2.tar.gz
$ cd git-1.7.2.2
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
在Linux上安装的时候会方便一点:
Fedora或者Redhat或者CentOS的话
$ yum install git-core
在Ubuntu或者Debian体系上的话
$ apt-get install git
在Mac上安装:
推荐使用图形化的Git安装工具:
http://sourceforge.net/projects/git-osx-installer/
也可以用MacPorts工具安装
$ sudo port install git-core +svn +doc +bash_completion +gitweb
Windows安装。。。。
你开发不嫌麻烦的吗,自己去下载安装exe
http://msysgit.github.com/
1.5 初次运行 Git 前的配置
一般在自己电脑上第一次用Git之前要配置一下Git环境。
Git提供了git config
这个工具来进行相关的配置,用来配置和读取相关的工作环境变量。这些变量主要可以存储在三个位置:
- /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用
git config
时用--system
选项,读写的就是这个文件。 - ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用
git config
时用--global
选项,读写的就是这个文件。 - 当前项目的 Git 目录中的配置文件(也就是工作目录中的
.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
用户信息配置(重要):
用户信息的准确性非常重要,尤其是想要在Github上进行打卡刷Contribution的话,一定要保证user.name
, user.password
, user.email
三者百分百的准确。
需要修改这些参数的话直接通过如下指令就行:
$ git config --global [user.name](http://user.name/) "John Doe”
$ git config --global user.email [johndoe@example.com](mailto:johndoe@example.com)
需要查看相关的用户信息的时候,可以使用-v
命令。
如果要查询某个特定环境变量也可以这样:
$ git config [user.name](http://user.name/)
1.6 获取帮助
需要获得Git各种工具的详细帮助信息的话,可以用help命令来帮助:
$ git help <verb>
$ git <verb> —help
$ man git-<verb>
2. Git 基础
2.1 获取 Git 仓库
假如现在你有一个文件夹想要作为一个Git仓库,一个指令就可以完成设定:
$ git init
这个指令会在文件夹里面创建一个/.git 的子目录,在这目录下是包含了初始GIT仓库所有必须的文件。差不多就是GIT仓库的架构骨干。
之后我们可以往通过git add来实现对文件的跟踪。然后执行git commit提交。add后面可以接具体要提交的文件特征,如果是.的话就代表提交所有。
$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version’
- 克隆现有的仓库
需要克隆某一个特定的仓库的话,可以使用git clone指令。这个指令其实也很好的体现了git的整体对比思想。
一个标准的克隆格式为:
$ git clone [URL]
当然我们也可以在URL后面加上一个昵称。例如:
$ git clone [URL] <nickname>
2.2 记录每次更新到仓库
Git这个工具牛逼的地方,在于记录每次更新到仓库,并且从这个仓库取出所有文件的工作拷贝。之后对这些文件进行修改,最后在一定阶段以后提交更新到仓库。
结合第一章的内容大致可以归类为下图:
GIT的状态
查看目前的文件系统处于什么状态,可以用:
$ git status
如果我们对文件系统里面的内容进行了修改,相关内容就会显示出来。
- 跟踪新文件
我们通过git add
指令来对文件进行跟踪:
$ git add FILENAME
这个时候再次使用git status
就能看到文件已经被追踪。
其中git add .
代表追踪整个仓库。
暂存已经修改的文件
把一个文件通过add
添加到暂存队列,这样的话在下次commit
的时候就会提交这个暂存的版本。如果在add
之后对相应文件又进行了修改,那么依然只会提交最后一个被add的版本。
$ git add [CONTRIBUTING.md](http://contributing.md/
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: [CONTRIBUTING.md](http://contributing.md/)
- 状态简览
通过git status -s
查看文件的状态,新添加的文件前面会有??
的标记。新添加到暂存区的文件前面有A
的标记,修改过的文件前面有M
的标记。已经被添加到暂存区但是又被修改的文件面前有MM
标记。
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
忽略文件
在Git仓库中我们可以创建一个./.gitignore
的文件来设定一些忽略选项。例如:
$ cat .gitignore
*.[oa]
*~
上面就表示忽略所有以o
和a
结尾的文件。文件 .gitignore
的格式规范为:
空行或者开头为#
的都被忽略
可以用标准的glob
模式匹配(glob是一种简化的正则表示法)
匹配可以用/
开头防止递归
匹配可以用/
结尾指定目录
忽略制定模式以外的文件或者目录,可以再模式前加!
取反。
查看尚未暂存的文件的更新内容可以用:
$ git diff
也可以查看已经暂存起来的变化
git diff --cached
2.3 查看提交历史
在多次更新或者长期提交之后,我们可能需要查看提交的历史和版本的历史,这个时候用到的指令是:
$ git log
这个指令不加参数输出的是所有的更新记录,最新的在最上方。但是一般我们会加上-p
参数,可以显示每次提交的差异,也会加上-n
参数,n是int,表示最近N条。
$ git log -p -2
我们也可以让git log显示的内容更加的简洁化。
$ git log —stat
同时也可以用--pretty
参数来让输出内容边的更加的易读,类似于一种多选的预设格式输出。
--online
会让每一个条目在同一行显示
$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
--format
可以非常自定义化的按照自己想要的格式输出历史记录
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
--graf
可以显示分支合并历史。
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of [git://github.com/dustin/grit](git://github.com/dustin/grit)
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
甚至也可以通过限制输出选项来设定具体的输出内容。具体可以去查询相关信息。
2.4 撤消操作
有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有--amend
选项的提交命令尝试重新提交:
$ git commit —amend
例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit —amend
我们也可以单独的取消暂存的文件
$ git status
可以查看现在推送列表中的文件的具体状态和文件名称。
我们可以通过下面的指令来单独取消某一个文件的推送或者修改请求:
$ git reset HEAD <filename>
这个指令在不加参数的情况下是一个相对来说比较安全的回退指令,但是如果确定要撤销暂存文件的修改可以用使用--hard
参数:
$ git reset —hard HEAD <filename>
如果不是撤销暂存文件,而是,对于文件的修改需要撤销,则需要另一个指令:
$ git checkout -- CONTRIBUTING.md
这个指令会撤销当前分支下所有对于目标文件的修改,慎用
2.5 远程仓库的使用
Git在创生之初就是提供多个编辑者在多个平台的任何时间可以远程共同完成一个项目,因此remote的思想贯穿了git设计的始终。因此对于远程仓库的利用非常重要。
查看git远程仓库非常简单,可以用$ git remote
查看当前本地已经配置的远程仓库的列表,也可以通过$ git config --list
查看具体有那些远程项目已经被配置到了配置里面。
如果需要参加到某一个远程项目当中去的话,我们可以使用:
$ git remote add <nickname> <url>
这样url对应的远程项目就会加入到本地的配置列表中。我们在有权限的情况下可以对远程项目进行push和版本更新。
然后有时候我们会在本地删除或者移动部分文件,导致本地的仓库和远程最新的版本相比缺少了某些项目,这个时候我们可以用:
$ git fetch <nickname>
来拉取缺少的文件。这个指令会从远程仓库中拉取所有的分支的引用。
如果使用$ git clone <url>
指令的话系统会自动把拉取的项目命名为origin。
而$ git pull
指令的话则会从该服务器上拉取并且合并到当前所在的分支,需要主要这些拉取克隆配对命令的差异。
如果要分享本地的项目,可以使用push指令。标准的格式是:
$ git push <nickname> <branch-name>
如果仅仅是 git push origin master`.
假如,本地拉取的是v0.1而之后其他编辑者提交了v0.2的话,我们必须要先拉取远程端的v0.2然后再进行本地的推送。
如果我们需要查看远程仓库的更多信息,可以使用:
$ git remote show origin
这个命令会列出git push默认的推送分支,远程和本地的分支,以及被移除的分支等等信息。
远程仓库的重命名:
$ git remote rename <old-nickname> <new-nickname>
这个操作会自动更新其他branch有关的记录和设定。
如果需要移除远程仓库的设定配置,则:
$ git remote rm <nickname>
2.6 打标签
git中对标签的支持非常全面。我们可以直接查看已有标签:
$ git tag
也可以用特定的模式进行查询:
$ git tag -l ‘v2.19*’
Git有两种类型的标签,轻量标签lightweight
和附注标签annotated
。
轻量标签本质是一个特定标签的引用,而附注标签是一个完整的git对象,是可被校验的。创建一个annotated tag
的方法如下:
$ git tag -a <tag name> -m “<description>”
如果在之后的使用中需要查看description的话,使用git show
指令来看:
$ git show <tag name>
如果需要增加一个清凉标签,则直接加上tag name即可:
$ git tag <tag name>
同时我们可以对过去的提交打上标签来方便查看,首先:
$ git log --pretty=online ##查看相关提交历史
$ git tag -a <tag name> <校验值(无需完整)>
标签在推送的时候不会默认推送到remote server,我们需要手动push tag:
$ git push <nickname> <tag name>
如果需要同时push多个tag的话,亦可以用简单的指令:
$ git push --tags
这样会把没有被推送的所有本地tag都推到服务器上。
2.7 Git 别名
git的别名功能为用户提供了高自定义度的使用体验,我们可以把大量的git指令设定别名。例如:
$ git config --global alias.<name> <command>
比如$ git config --global alias.psh push
进行设定之后,$ git psh
就和$ git push
等价了。
甚至我们也可以把git的组合指令设定成一个别名:
$ git config --global alias.last 'log -1 HEAD’
甚至我们可以设定外部指令为一个别名,这个对自己开发git工具很有帮助:
$ git config --global alias.visual '!gitk’
只要在外部指令前面加上一个!
即可
3. Git 分支
3.1 分支简介
GIT本质保存的是一系列文件的快照。在GIT中提交的时候只会保存一个commit对象,这也是为什么git add 后必须进行一次commit提交的原因。但是提交分为首次提交和普通提交,首次提交是没有一个祖先分支的,但是普通提交存在祖先分支。
使用git commit
新建一个提交对象之前,GIT会先计算每一个子目录的校验值,然后在repo中把这些目录保存为tree对象,之后git在提交的过程中,除了提交相关的信息和文件之外,还会提交这个tree的指向指针,以便在未来复现逻辑联系和快速重现快照。
类似的逻辑拓扑如图下:
拓扑逻辑我们也可以来看一下单个提交对象的结构和多个提交对象之间的关系。注意区分和master分支的关系。
拓扑逻辑 拓扑逻辑在GIT中,创建一个全新的分支使用如下指令:
$ git branch <branch_name>
这个指令严格来说不是新建了一个快照,而是在当前的commit版本上创建了一个新的分支指针。但是问题来了,这个时候GIT如何确定用户在哪个分支上工作呢。事实上git branch
仅仅创建了一个全新的分支,但是并不会把用户的工作区域同时转换到新的分支中去。
前往其他的分支可以使用如下的指令:
$ git checkout <branch_name>
3.2 分支的新建与合并
在GIT中,分支可以很轻松进行新建和合并。这个模式本质非常利于多人协作项目。
例如在tensorflow项目中,出现了两个错误问题issue,issue#21
和issue#32
。这个时候就有两个开发者分别去处理各自的问题。其中一个人开始修改issue21
,然后逐步推送,逐渐获得了一个修改串,最后的修复版本是issue21_kai
;另一个人开始修复issue32
,最后的修复版本是issue32_kai
,这个时候对于最初发生分支的版本,两条修复路线出现了分叉。这个时候就需要进行合并分支。
这个时候我们先回到master分支,在进行合并指令merge:
$ git checkout master
$ git merge issue21_kai
$ git merge issue32_kai
GIT会自动的帮助用户选择并且对比提交版本的新旧,并且按照一套智能化的提交规则来进行最后的master分支合并。这个过程中最后被合并后的分支拥有多个祖先分支,需要注意。
合并拓扑但是如果仅仅是一个问题的hotfix,虽然最后合并的时候也是用的merge指令,但是和上面的多分支合有比较大的流程上的区别。
但是有时候遇到A B两个分支同时修改了同一个文件的问题,这个时候GIT无法擅自进行合并,于是GIt只能进行合并,但是无法进行提交。需要用户人为地去进行裁决。
这个时候使用git status
才查看具体的冲突问题。
任何未解决的冲突文件都会以unmerged
的状态被列出。我们可以在有冲突的文件里看到GIT帮我们添加的冲突解决标记,GIT会在冲突部分标注修改的来源分支名称,从而我们可以方便快速的查阅和修改。
我们甚至可以使用一个图形界面工具来解决merge冲突问题。也就是mergetool命令:
$ git mergetool
我们可以在选项上的merge tool candidates
里面找到可以用的合并工具列表。然后输入名称进行选择。
3.3 分支管理
上面介绍了GIT分支的基本操作,创建、合并、删除。之后就需要对分支进行管理,在大型项目或者remote协作项目中,可能会出现成百上千个分支,这个时候出色的分支管理是一个大型项目成本控制和协作安排的核心需求。
通过$ git branch
命令我们可以获得当前所有分支的清单。
其中在master分之前会有一个*
号。
$ git branch
iss53
* master
testing
在清单中筛选出已经合并的或者尚未合并的分支可以使用如下参数:
$ git branch --merged
$ git branch --no-merged
一般来说列表中没有 * 的分支其实都可以用$ git branch -d
来进行删除。从而精简列表。
3.4 分支开发工作流
我们通过GIT出色的分支操作功能和分支管理功能,引申出了一个全新的开发工作流程。也就是分支开发工作流。
因为GIT使用了简单的三方合并,所以就算再较长的一段时间内,反复多次把某个分支合并到另一个也不是什么问题。我们可以同时开启多个开放的分支用于完成不同的任务,最后对分支进行合并就可以了。
其实分支的本质就是随着提交对象不断移动的指针,稳定分支的指针一般会在提交历史中落后一截,是因为很多bata和alpha版本还是需要大量的测试和返工。
分支图GIT还有一个重要的功能是 特性分支 。
任何一个项目都可以使用特性分支。特性分支指的是一个短期的用来实现单一特性或者功能的工作分支。
而且这些特性分支在提交合并之前其实都是本地分支,不会对发布版本有任何影响。
3.5 远程分支
远程分支是远程repo中分支的索引。是一些无法移动的本地分支。只有在git网络交互的时候才会发生更新。
如果我们连接一个公司内部的Github Enterprise服务器,我们从上面clone一个项目下来以后,在本地会所为一个origin/master
的分支存在,但是这个分支我们是不能编辑的,所以本地的git为了让我们能够编辑,会后台创建一个叫做master的分支,我们可以fetch到这个master上进行修改。
如果我们再本地的master上做了修改,其他编辑者往remote的repo推送了自己的修改,这个时候相当于我们本地的和远程的项目发生了分叉。这个时候本地的origin/master还是会保持不动,至少下一次通讯。
这个时候我们可以运行$ git fetch origin
来同步远程服务器上的数据到本地。同时git fetch指令会更新remote索引。当然,origin只是一个别名,在git remote add
指令下可以对远程repo进行任意的命名。
如果我们有一个分支叫做branCH需要和其他人一起开发,repo昵称是devapp,我们可以使用$ git push devapp branCH
把分支推送到远程,别人就可以一起来编辑这个分支。
甚至可以把本地分支推送到远程的不同命名的分支上去:
$ git push devapp branCH:CHnarb
此时再次从服务器上获取数据时,会得到一个新的远程分支devapp/branCH
。
但是此时无法编辑这个分支。我们只会有一个无法移动的devapp/branCH
分支。
如果需要弄一份自己的branCH分支来进行开发,则需要重新分化一个新的分支出来:
$ git checkout -b <local_branch_name> devapp/branCH
这样就能来到新的复制的本地分支,从而继续开发。
从远程分支checkout出来的本地分支被称为跟踪分支。在跟踪分支下输入git push指令,GIT会自动判断需要推送的远程分支。同时在git pull时候会获得是所有的远程索引。
如果要删除某个远程分支,指令比较鬼畜(注意冒号前的空格。。。):
$ git push <repo_name> :<branch_name>
3.6 变基
把一个分支里面的修改整合到另一个分支的方法主要是merge和rebase。其中rebase就是所谓的变基。
merge是一个最为简易的整合分支方法,还有一种是把一条分支线上的一个分支的改变打到另一个分支线的分支上,这个叫做rebase,也就是变基。
例如在分支C3中,我们把改动和变化以补丁的形式打到C4上面。指令如下:
$ git checkout experiment
$ git rebase master
原理其实就是回到两个分支最近的共同祖先。然后根据当前所在分支后续的历次提交,生成一系列文件补丁,然后以base分支最后一个提交对象为新的出发点,进行总打包。最后成为新的最近补丁。拓扑如下:
之后只要回到master分支然后进行一次快速合并,这就是rebase指令的流程。
变基操作是一个非常灵活的功能,如果我们像对一些非自己维护的补丁进行修改和改进,这个时候我们最后线进行变基,然后在进行提交。这样维护者就可以很轻松的进行整合。需要注意的,无论是三方合并还是变基,最终的快照内容是一致的,只是最后的提交历史会不同。
变基也可以在非master分支上进行,并不一定要根据分化之前的分支。如果对于一个多重分支结构:
事实上我们可以用rebase指令跳过server的分支串,直接把client的改动合并到master分支上,这个时候我们需要使用onto参数才重新制定基地分支:
$ git rebase --onto master server client
意思就是求client和server分支后的差异,然后以master为底,进行重演。这个操作以后进行master分支的快进就可以了。保证master的最新版。
$ git checkout master
$ git merge client
如果这个时候需要把server的内容也打进来,则我们可以直接把server分支变基到master么不用再切换到server分支串上:
$ git rebase master server
变基拓扑
此时client和server都已经提交到了master上了,这个时候直接删掉两个合并完的分支就好了:
$ git branch -d client
$ git branch -d server
rebase操作本身还是存在一定风险的,其实要规避也很简单,遵循一条原则:
一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行变基操作。
4. 服务器上的 Git
4.1 协议
GIT主要使用四种协议:本地传输协议,SSH传输协议,Git传输协议和HTTP协议。
本地协议的话,例如一群人在同一台服务器上维护编辑一个项目,则可以使用:
$ git clone <本地目录>
这个时候就是用了本地传输协议。
SSH协议是非常常用的,我们通过下面的指令远程clone仓库:
$ git clone [ssh://user@server/project.git](ssh://user@server/project.git)
GIT协议是包含在git安装包里面的一个特殊协议,使用一个特殊端口9418。repo要支持git协议,需要创建一个git-daemon-export-ok
文件,但是这个协议一旦开放,任何人可以用任何URL进行推送。不安全。
HTTP/S协议。这个协议非常优雅,直接把repo放在http根目录下,配一个特定的post-update挂钩hook就可以。然后每个有权限访问服务器上web服务器的用户都可以进行clone。安全高效轻量的一个协议。
4.2 在服务器上搭建 Git
在假设一个git服务器开始之前,需要把现有的repo导出,变成裸repo。也就是一个不包括当前工作目录的repo。使用如下指令生成:
$ git clone --bare <nickname> <repo_name>.git
Git clone其实本质上类似于git init加上git fetch。
之后我们需要把裸repo移动到服务器上,假设域名为git.eg.com。我们则直接把裸repo复制到这个目标的服务器就可以了。
$ scp -r <repo_name>.git user@git.eg.com:/opt/git/<repo_name>.git
之后如果有用户需要clone这个仓库的话,直接通过:
$ git clone user@git.eg.com:/opt/git/<repo_name>.git
如果某个ssh用户对于这个remote repo有写权限,则可以直接推送。如果到这个repo的目录中运行git init命令,并且加上share参数,则这个repo会被git自动设定为可写。
$ ssh [user@git.eg.com](mailto:user@git.eg.com)
$ cd /opt/git/<repo_name>.git
$ git init --bare --share
然而对于生产环境来说,Git服务器架设最困难的部分在于账户管理。因为一个项目或者一个企业的生产环境对于不同用户的权限和repo权限的分别管理非常重要。如果能和Amazon的权限设定功能一样完备就再好不过了。这个时候如果是小型企业,一般推荐直接启用ssh白名单模式。具体方法参考知识库ssh的内容即可。
4.3 生成 SSH 公钥
基本常识,略过不提
4.4 配置服务器
本质原理为SSH权限控制和Git协议分发。具体可查阅官方文档
4.5 Git 守护进程
我们可以通过Git协议简历一个机遇守护进程的仓库,用于快速无授权Git数据防伪。一般建议只在内网中公开只读项目。主要优点是省去配置大量ssh公钥的麻烦,虽然这一步可以用ansible推送脚本来批量完成。
设定这个Git协议是比较容易的,通过如下指令:
$ git daemon --reuseaddr --base-path=/opt/git/ /opt/git/
reuseaddr让服务器在无需等待旧连接超时的情况下重启。base-path允许用户在没有完全指定路径的条件下clone。
我们甚至可以通过脚本文件的形式来让这个进程以守护进程的方式运行。例如编辑/etc/event.d/local-git-daemon
文件。
接下来,你需要告诉 Git 哪些仓库允许基于服务器的无授权访问。 你可以在每个仓库下创建一个名为git-daemon-export-ok
的文件来实现。
$ cd /path/to/project.git
$ touch git-daemon-export-ok
4.6 Smart HTTP
简易情况下,我们用SSH协议进行git授权访问,用git协议进行无授权访问,但是http协议可以同时接受上面两种的访问形式。
我们只要在git服务器上启用一个git自带的git-http-backend的CGI脚本,这脚本就会处理git fetch和git push等命令,并向http url发送请求路径和头部信息。我们可以用Apache或者Nginx来作为CGI服务器。
$ sudo apt-get install apache2 apache2-utils
$ a2enmod cgi alias env
之后在Apache配置中添加对应设置
SetEnv GIT_PROJECT_ROOT /opt/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
<Directory "/usr/lib/git-core*">
Options ExecCGI Indexes
Order allow,deny
Allow from all
Require all granted
</Directory>
如果需要实现写操作权限验证,添加下方设定
<LocationMatch "^/git/.*/git-receive-pack$">
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/git/.htpasswd
Require valid-user
</LocationMatch>
这么设定的话需要我们创建爱一个包含所有合法用户密码的.htaccess
文件
$ htdigest -c /opt/git/.htpasswd "Git Access” <username>
4.7 GitWeb
具体可以查看官网文档,其实就是一个自搭Git服务器的基础web页面设置。
4.8 GitLab
Google旗下的Git托管平台,有企业版。具体查看GitLab官方文档
网友评论