1. 概述
对于软件版本管理工具,酷讯决定摒弃CVS而转向Git了。
为什么要选择Git? 你真正学会使用Git时, 你就会觉得这个问题的回答是非常自然的。然而当真正需要用文字来回答时,却觉得文字好像不是那么够用。 咳,该则么回答呢?
其实,关键的问题不在于如何回答这个问题。 问题的关键是公司已经决定使用它了。那么,我们的程序员们! 请开动你们的浏览器,请拿出你的搜索引擎工具,去自己发掘答案吧。在这里,我只能给你们一个最朦胧的感觉。
Git和 CVS、SVN不同,是一个分布式的源代码管理工具。Linux内核的代码就是用Git管理的。它很强,也很快。它给我们带来的直接好处有:
1. 傻瓜都会的初始化,git init, git commit -a, 就完了。对于随便写两行代码就要放到代码管理工具里的人来说,再合适不过。也可以拿git做备份系统,或者同步两台机器的文档,都很方便。
2. 绝大部分操作在本地完成,不用和集中的代码管理服务器交互,终于可以随时随地大胆地check in代码了。 只有最终完成的版本才需要向一个中心的集中的代码管理服务器提交。
3. 每次提交都会对所有代码创建一个唯一的commit id。不像CVS那样都是对单个文件分别进行版本的更改。所以你可以一次性将某次提交前的所有代码check出来,而不用考虑到底提交过那些文件。(其实 SVN也可以做到这点)
4. branch管理容易多了,无论是建立新的branch,还是在branch之间切换都一条命令完成,不需要建立多余的目录。
5. branch之间merge时,不仅代码会merge在一起,check in历史也会保留,这点非常重要。
6. … 太多了
当然,Git也会带给我们一些困难,首先,你想要使用好git,就要真正明白它的原理,理解它的观念, 对以那些CVS的熟手来说,改变你已经固有的纯集中式源代码管理的观念尤为重要,同时也会让你觉得有些困难。在使用git的初期,你可能会觉得有些困难,但等你逐渐明白它时,你绝对会喜欢上它。这是一定的,就像我问你“喜欢一个温吞如水、毫无感觉的主妇,还是喜欢一个奔放如火,让你爱的痴狂恨的牙痒的情人”一样毋庸置疑。
下面,就让我们进入学习Git之旅…
请记住,这只是一个非常简单而且初级的教程, 想要成为git的专家,需要各位同事不断的自己深入挖掘。
2. Git基础命令
2.1 创建Git库—git-init
你们曾经创建过CVS的库么?应该很少有人操作过吧?因为很多人都是从CVS库里checkout代码。同样,在合作开发中,如果你不是一个代码模块的发起者,也不会使用到这个命令,更多的是使用git-clone(见2.7节)。 但是,如果你想个人开发一个小模块,并暂时用代码管理工具管理起来(其实我就常这么做,至少很多个人开发过程都可以保留下来,以便备份和恢复),创建一个 Git库是很容易和方便的。
对于酷讯来说,当一个代码的Git库创建后,会添加代码文件到库里,并将这个库放到公司一个专门用来进行代码管理的服务器上,使大家可以在以后 clone(不明白?没关系,继续往后看就明白了)它。对于个人来说,你可以随便将这个库放到哪里,只要你能访问的到就行。
创建一个Git库是很容易和方便的,只要用命令 git-init 就可以了。在Git1.4之前(包括git1.4)的版本,这个命令是git-init。
a) $ mkdir dir
b) $ cd dir
c) $ git-init
这样,一个空的版本库就创建好了,并在当前目录中创建一个叫 .git 的子目录。以后,所以的文件变化信息都会保存到这个目录下,而不像CVS那样,会在每个目录和子目录下都创建一个讨厌的CVS目录。
在.git目录下有一个config文件, 需要我们添加一下个人信息后才能使用。否则我们不能对其中添加和修改任何文件。
原始的config文件是这样的,
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
我们需要加入
[user]
name = xxx
emai= xxx@kuxun.cn
现在已经创建好了一个 git 版本库,但是它是空的,还不能做任何事情,下一步就是怎么向版本库中添加文件了。如果希望忽略某些文件,需要在git库根目录下添加. gitignore文件。
2.2 一条重要的命令 -- git-update-index
在介绍如何向git库中添加文件前,不得不先介绍git-update-index命令。这条命令可能会使很多熟悉CVS的用户疑惑, 一般来说,我们向一个源代码管理库提交代码的更改,都会抽象为以下的动作:更改文件;向源码管理系统标识变化;提交。比如从一个CVS库里删除一个文件,需要先删除文件,然后cvs delete; 最后cvs commit。
因此, git-update-index就是向源码管理系统标识文件变化的一个抽象操作。说的简要一些,git-update-index命令就是通知git库有文件的状态发生了变化(新添、修改、删除等待)。这条命令在早期的git版本中是非常常用的。 在新的git版本(1.5版本及以后)已经被其它命令包装起来,并且不推荐使用了。
git-update-index最常用的方式有以下两种,更多功能请man git-update-index。
方法一:git-update-index --add 文件名列表。 如果文件存在,则这条命令是向git库标识该文件发生过变化(无论是否该文件确实被修改过),如果文件不存在,则这条命令是向git库表示需要加入一个新文件。l
方法二: git-update-index --force-remove 文件名列表。 这表示向git库表示哟啊从库中删除文件。无论该文件是否已经被删除,这条命令仅仅是通知git库要从库中删除这些文件。这些文件都不会受影响。l
因此,git-update-index仅仅是向git库起到一个通知和标识的作用,并不会操作具体的文件。
2.3 向git库中添加或删除文件 – git-add、git-rm
其实,说使用git-add命令向git库里添加文件是不对的, 或者说至少是不全面的。git-add 命令的本质是命令"git-update-index --add” 的一个包装。因此,git-add除了可以添加文件,还可以标识文件修改。在调用了git-add后,才可以做commit操作。git-rm 也是一样, 它是git-update-index --force-remove的一个包装。
对于git-add来说, 如果在一个目录下调用了git-add * ,则默认是递归将子目录中所有文件都add到git库中。对于git-rm来说,也是一样。 这点和CVS有较大区别。
此外,我们还可以通过命令git-ls-files来查看当前的git库中有那些文件。
2.4 查看版本库状态—git-status
通过该命令,我们可以查看版本库的状态。可以得知那些文件发生了变化,那些文件还没有添加到git库中等等。 建议每次commit前都要通过该命令确认库状态。以避免误操作。
其总,最常见的误操作是, 修改了一个文件, 没有调用git-add通知git库该文件已经发生了变化就直接调用commit操作, 从而导致该文件并没有真正的提交。如果这时如果开发者以为已经提交了该文件,就继续修改甚至删除这个文件,那么修改的内容就没有通过版本管理起来。如果每次在提交前,使用git-status查看一下,就可以发现这种错误。因此,如果调用了git-status命令,一定要格外注意那些提示为 “Changed but not updated:”的文件。 这些文件都是与上次commit相比发生了变化,但是却没有通过git-add标识的文件。
2.5 向版本库提交变化 – git-commit
直接调用git-commit命令,会提示填写注释。也可以通过如下方式在命令行就填写提交注释:git-commit -m "Initial commit of gittutor reposistory"。 注意,和CVS不同,git的提交注释必须不能为空。否则就会提交失败。
git-commit还有一个 –a的参数,可以将那些没有通过git-add标识的变化一并强行提交,但是不建议使用这种方式。
每一次提交,git就会为全局代码建立一个唯一的commit标识代码,用户可以通过git-revert命令恢复到任意一次提交时的代码。 这比CVS不同文件有不同的版本呢号管理可方便多了。(和SVN类似)
如果提交前,想看看具体那些文件发生变化,可以通过git-diff来查看, 不过这个命令的输出并不友好。因此建议用别的工具来实现该功能。在提交后,还可以通过git-log命令来查看提交记录。
2.6 分支管理 – git-branch
我们迎来了git最强大,也是比CVS、SVN强大的多的功能 — 分支管理。
大概每个程序员都会经常遇到这样的情况:
1. 需要立刻放下手头的工作,去修改曾经一个版本的bug并上线,然后再继续当的工作。
2. 本想向中心库commit一个重要修改,但是由于需要经常备份代码,最终不得不频繁的向中心库commit。从而导致大量无用的commit信息被保留在中心库中。
3. 将一次修改提交同事进行code review, 但是由于同事code review比较慢, 得到反馈时,自己的代码已经发生了变化,从而倒是合并异常困难
这些场景,如果用CVS或者SVN来解决,虽说不一定解决不了,但过程之繁琐,之复杂,肯定另所有人都有生不如死的感觉吧!究其关键,就是CVS或者 SNV的branch管理太复杂,基本不具可用性。
在 git 版本库中创建分支的成本几乎为零,所以,不必吝啬多创建几个分支。当第一次执行git-init时,系统就会创建一个名为”master”的分支。 而其它分支则通过手工创建。下面列举一些常见的分支策略,这些策略相信会对你的日常开发带来很大的便利。
1.创建一个属于自己的个人工作分支,以避免对主分支 master 造成太多的干扰,也方便与他人交流协作。l
2.当进行高风险的工作时,创建一个试验性的分支,扔掉一个烂摊子总比收拾一个烂摊子好得多。l
3.合并别人的工作的时候,最好是创建一个临时的分支用来合并,合并完成后在“fatch”到自己的分支(合并和fatch后面有讲述,不明白就继续往下看好了)l
2.6.1 查看分支 – git-branch
调用git-branch可以查看程序中已经存在的分支和当前分支
2.6.2 创建分支 – git-branch 分支名
要创建一个分支,可以使用如下方法:
1. git-branch 分支名称
2. git-checout –b 分支名
使用第一种方法,虽然创建了分支,但是不会将当前工作分支切换到新创建的分支上,因此,还需要命令”git-checkout 分支名” 来切换, 而第二种方法不但创建了分支,还将当前工作分支切换到了该分支上。
另外,需要注意,分支名称是有可能出现重名的情况的, 比如说,我在master分支下创建了a和b两个分支, 然后切换到b分支,在b分支下又创建了a和c分支。 这种操作是可以进行的。 此时的a分支和master下的a分支实际上是两个不同的分支。 因此,在实际使用时,不建议这样的操作,这样会带来命名上的疑惑。
2.6.3 删除分支 – git-branch –D
git-branch –D 分支名可以删除分支,但是需要小心,删除后,发生在该分支的所有变化都无法恢复。
2.6.4 切换分支 – git-checkout 分支名
如果分支已经存在, 可以通过 git-checkout 分支名 来切换工作分支到该分支名
2.6.5 查看分支历史 –git-show-branch
调用该命令可以查看分支历史变化情况。 如:
* [dev1] d2
! [master] m2
--
* [dev1] d2
* [dev1^] d1
* [dev1~2] d1
*+ [master] m2
在上述例子中, “--”之上的两行表示有两个分支dev1和master, 且dev分支上最后一次提交的日志是“d2”,master分支上最后一次提交的日志是”m2”。 “--”之下的几行表示了分支演化的历史,其中 dev1表示发生在dev分支上的最后一次提交,dev^表示发生在dev分支上的倒数第二次提交。dev1~2表示发生在dev分支上的倒数第三次提交。
2.6.6 合并分支 – git-merge
git-merge的用法为:git-merge “some memo” 合并的目标分支 合并的来源分支。如:
git-merge master dev1~2
如果合并有冲突,git会由提示,当前,git-merge已经很少用了, 用git-pull来替代了。
用法为:git-pull 合并的目标分支 合并的来源分支。 如git-pull . dev1^
2.7 远程获取一个git库 git-clone
在2.1节提到过,如果你不是一个代码模块的发起者,也不会使用到git-init命令,而是更多的是使用git-clone。通过这个命令,你可以从远端完整获取一个git库,并可以通过一些命令和远端的git交互。
基于git的代码管理的组织结构,往往形成一个树状结构,开发者一般从某个代码模块的管理者的git库通过git-clone取得开发环境,在本地迭代开发后,再提交给该模块的管理者,该模块的管理者检查这些提交并将代码合并到自己的库中,并向更高一级的代码管理者提交自己的模块代码。
对于酷讯来说,公司会有一个中心的git库, 大家在开发时,都是从中心库git-clone获取最新代码。
git-clone的使用方法如下: git-clone [ssh://]username@ipaddr:path。 其中, “ssh://”可选,也有别的获取方式,如rsync。 Path是远端git的根路径,也叫repository。
通过git-clone获取远端git库后,.git/config中的开发者信息不会被一起clone过来。仍然需要为.git/config文件添加开发者信息。此外,开发者还需要自己添加. gitignore文件
另外,通过git-clone获取的远端git库,只包含了远端git库的当前工作分支。如果想获取其它分支信息,需要使用”git-branch –r” 来查看, 如果需要将远程的其它分支代码也获取过来,可以使用命令” git checkout -b 本地分支名 远程分支名”,其中,远程分支名为git-branch –r所列出的分支名, 一般是诸如“origin/分支名”的样子。如果本地分支名已经存在, 则不需要“-b”参数。
2.8 从远程获取一个git分支 – git-pull
与git-clone不同, git-pull可以从任意一个git库获取某个分支的内容。用法如下:
git-pull username@ipaddr: 远端repository名 远端分支名:本地分支名。这条命令将从远端git库的远端分支名获取到本地git库的一个本地分支中。其中,如果不写本地分支名,则默认pull到本地当前分支。
需要注意的是,git-pull也可以用来合并分支。 和git-merge的作用相同。 因此,如果你的本地分支已经有内容,则git-pull会合并这些文件,如果有冲突会报警。
2.9 将本地分支内容提交到远端分支 – git-push
git-push和git-pull正好想反,是将本地某个分支的内容提交到远端某个分支上。用法:
git-push username@ipaddr: 远端repository名 本地分支名:远端分支名。这条命令将本地git库的一个本地分支push到远端git库的远端分支名中。
需要格外注意的是,git-push好像不会自动合并文件。这点我的试验表明是这样,但我不能确认是否是我用错了。因此,如果git-push时,发生了冲突,就会被后push的文件内容强行覆盖,而且没有什么提示。 这在合作开发时是很危险的事情。
2.10 库的逆转与恢复 – git-reset
库的逆转与恢复除了用来进行一些废弃的研发代码的重置外,还有一个重要的作用。比如我们从远程clone了一个代码库,在本地开发后,准备提交回远程。但是本地代码库在开发时,有功能性的commit,也有出于备份目的的commit等等。总之,commit的日志中有大量无用log,我们并不想把这些 log在提交回远程时也提交到库中。 因此,就要用到git-reset。
Git-reset的概念比较复杂。它的命令形式:git-reset [--mixed | --soft | --hard] []
命令的选项:
--mixed
这个是默认的选项。 如git-reset [--mixed] dev1^(dev1^的定义可以参见2.6.5)。它的作用仅是重置分支状态到dev1^, 但是却不改变任何工作文件的内容。即,从dev1^到dev1的所有文件变化都保留了,但是dev1^到dev1之间的所有commit日志都被清除了,而且,发生变化的文件内容也没有通过git-add标识,如果您要重新commit,还需要对变化的文件做一次git-add。 这样,commit后,就得到了一份非常干净的提交记录。
--soft
相当于做了git-reset –mixed,后,又对变化的文件做了git-add。如果用了该选项, 就可以直接commit了。
--hard
这个命令就会导致所有信息的回退, 包括文件内容。 一般只有在重置废弃代码时,才用它。 执行后,文件内容也无法恢复回来了。
2.11 更多的操作
之前的10节只简要介绍了git的基本命令,更多的细节可以去linux下man git的文档。此外,《人体大胆瓣开下部自慰》高清资源,《人体大胆瓣开下部自慰》1080p在线观看 - 侠客电影网 也有不少更详细的介绍。
3. 基于git的合作开发
对于酷讯来说,当我们采用了Git,如何进行合作开发呢? 具体步骤如下:
3.1 获取最新代码
酷讯会准备一个中心git代码库。首先,我们将整理好的代码分模块在git中心库中建立git库。并将文件add到中心库中。 接下来,开发者通过git-clone将代码从中心库clone到本地开发环境。
对于较大的项目,我们还建议每个组选择一个负责人,由这个负责人负责从中心库获取和更新最新的代码,其它开发者从这个负责人的git代码库中clone代码。此时,对开发者来说,这个负责人的git库就是中心库了。
3.2 开发者在本地进行迭代开发
当用户将代码clone到本地后, 就可以进行本地的迭代开发,建议用户不要在master分支上开发,而是建立一个开发分支进行开发。 在本地开发中,用户可以随意的创建临时分支,随意commit。
3.3 开发者请其它同事进行code review
当本地开发完毕,可以请其它同事进行code review。过程为:
1. user2通通过git-pull命令,将开发者(user1)的开发分支(dev)pull到user2本地的一个tmp分支,并切换工作分支到该分支上进行code review。
2. 完成code review后, user2切换回其原有开发分支继续开发,并告知user1已经修改完毕。
3. User1将user2的tmp分支git-pull到本地tmp分支,并和dev分支进行merge。最终得到一个code review后的dev分支。
当然,user2也可以直接坐在user1旁边在他的代码上进行review。而不需要走上述步骤。(图中第7步,不是git-pull,而是直接在 dev分支上和user1边review边modify)
3.4 和中心库进行代码合并
使用过CVS的人都知道, 在commit之前,都要做一次cvs update,以避免和中心库冲突。Git也是如此。
现在我们已经经过了code review, 准备向中心库提交变化了, 在开发的这段时间,也许中心库发生了变化, 因此,我们需要在向中心库提交前,再次将中心库的master分支git-pull到本地的master分支上。并且和dev分支做合并。最终,将合并的代码放入master分支。
如果开发过程提交日志过多,可以考虑参照2.10节的介绍做一次git-reset。
此外,如果发现合并过程变化非常多, 出于代码质量考虑,建议再做一次code review
3.5 提交代码到中心库
此时,已经完全准备好提交最终的代码了。 通过git-push就可以了。
3.6 合作流程总结
大家可以看到,使用git进行合作开发,这一过程和CVS有很多相似性,同时,增强了以下几个环节:
1. 开发者在本地进行迭代开发,可以经常的做commit操作且不会影响他人。 而且即使不在线也可以进行开发。只需要最后向中心库提交一次即可。
2. 大家都知道,如果CVS管理代码,由于我们会常常做commit操作。但是在commit之前cvs update时常会遇到将中心库上的其它最新代码checkout下来的情况,此时,一旦出现问题,就很难确认到底是自己开发的bug还是其它用户的代码带来了影响。 而使用git则避免了用户间的开发互相影响。
3. 更有利于在代码提交前做code review。 以往用cvs, 都是代码提交后才做code view。如果发生问题, 也无法避免服务器上有不好的代码。 但是用git, 真正向中心库commit前,都是在本地开发,可以方便的进行code review, 然后才提交到中心库。更有利于代码质量。而且, 大家应该可以感到,使用git的过程中,更容易对代码进行code review,因为影响因素更小。
4. 创建多分支,更容易在开发中进行多种工作,而使工作间不会互相影响。 比如user2对user1的代码进行code review时,就可以非常方便的保留当时的开发现场,并切换到user1的代码分支,在code review完毕后,也可以非常方便的切换会曾经被中断的工作现场。
诚然,带来这些好处的同时,确实也使得操作比CVS复杂了一些。但我们觉得和前面所能获得的好处相比,这些麻烦是值得的。 当大家用惯了之后会发现,这并不增加多大的复杂性, 而且开发流程会更加自然。
- Git历史
同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,于是整个项目组开始启用分布式版本控制系统 BitKeeper 来管理和维护代码。
到 2005 年的时候,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux的缔造者 Linus Torvalds 林纳斯·托瓦兹)不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。他们对新的系统订了若干目标:
• 速度
• 简单的设计
• 对非线性开发模式的强力支持(允许上千个并行开发的分支)
• 完全分布式
• 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
正在上传…重新上传取消
- Git与svn对比
- Svn
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就郁闷了。
下图就是标准的集中式版本控制工具管理方式:
正在上传…重新上传取消
集中管理方式在一定程度上看到其他开发人员在干什么,而管理员也可以很轻松掌握每个人的开发权限。
但是相较于其优点而言,集中式版本控制工具缺点很明显:
- 服务器单点故障
- 容错性差
- Git
Git是分布式版本控制系统,那么它可以没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
下图就是分布式版本控制工具管理方式:
正在上传…重新上传取消
- git工作流程
一般工作流程如下:
- 从远程仓库中克隆 Git 资源作为本地仓库。
- 从本地仓库中checkout代码然后进行代码修改。
- 在提交前先将代码提交到暂存区。
- 提交修改。提交到本地仓库。本地仓库中保存修改的各个历史版本。
- 在修改完成后,需要和团队成员共享代码时,可以将代码push到远程仓库。
下图展示了 Git 的工作流程:
正在上传…重新上传取消
- Git的安装
最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑。不过,慢慢地有人把它移植到了Windows上。现在,Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。由于开发机大多数情况都是windows,所以本教程只讲解windows下的git的安装及使用。
-
- 软件下载
下载地址:Git - Downloads
正在上传…重新上传取消
正在上传…重新上传取消
参考资料中安装包已经下载完毕,根据不同的操作系统选择对应的安装包。
-
- 软件安装
- 安装git for windows
- 软件安装
正在上传…重新上传取消
正在上传…重新上传取消
一路“Next”使用默认选项即可。
-
-
- 安装TortoiseGit
-
正在上传…重新上传取消
正在上传…重新上传取消
一路“Next”使用默认选项即可。
默认选项下会启动配置画面:
正在上传…重新上传取消
由于目前只有英文语言包,默认即可继续下一步。
配置git.exe,在4.2.1中已经安装过git-for-windows了所以在此找到git.exe所在的目录。
正在上传…重新上传取消
配置开发者姓名及邮箱,每次提交代码时都会把此信息包含到提交的信息中。
正在上传…重新上传取消
使用默认配置,点击“完成”按钮完成配置。
正在上传…重新上传取消
完整完毕后在系统右键菜单中会出现git的菜单项。
正在上传…重新上传取消
-
-
- 安装中文语言包
-
安装中文语言包并不是必选项。可以根据个人情况来选择安装。
正在上传…重新上传取消
正在上传…重新上传取消
直接“下一步”完整完毕。
鼠标右键选择Settings
正在上传…重新上传取消
语言包安装完毕后可以在TortoiseGit的设置中调整语言
正在上传…重新上传取消
- 使用git管理文件版本
- 创建版本库
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。由于git是分布式版本管理工具,所以git在不需要联网的情况下也具有完整的版本管理能力。
创建一个版本库非常简单,可以使用git bash也可以使用tortoiseGit。首先,选择一个合适的地方,创建一个空目录(D:\git)。
-
-
- 使用GitBash
-
在当前目录中点击右键中选择Git Bash来启动。
正在上传…重新上传取消
创建仓库执行命令:
$ git init
正在上传…重新上传取消
-
-
- 使用TortoiseGit
-
使用TortoiseGit时只需要在目录中点击右键菜单选择“在这里创建版本库”
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
版本库创建成功,会在此目录下创建一个.git的隐藏目录,如下所示:
正在上传…重新上传取消
版本库:“.git”目录就是版本库,将来文件都需要保存到版本库中。
工作目录:包含“.git”目录的目录,也就是.git目录的上一级目录就是工作目录。只有工作目录中的文件才能保存到版本库中。
-
- 添加文件
- 添加文件步骤
- 添加文件
在D:\git目录下创建一个mytest.txt文件
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
文本文件变为带“+”号的图标:
正在上传…重新上传取消
提交文件
在mytest.txt上再次点击右键选择“提交”,此时将文件保存至版本库中。
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 工作区和暂存区
-
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
什么是工作区(Working Directory)?
工作区就是你在电脑里能看到的目录,比如我的git文件夹就是一个工作区。
其实git目录是工作区,在这个目录中的“.git”隐藏文件夹才是版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
如下图所示:
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
分支和HEAD的概念我们稍后再讲。前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
-
- 修改文件
- 提交修改
- 修改文件
被版本库管理的文件不可避免的要发生修改,此时只需要直接对文件修改即可。修改完毕后需要将文件的修改提交到版本库。
在修改后的mytest.txt(修改后图标变成红色感叹号)文件上点击右键,然后选择“提交”,和之前的提交方式一样。
正在上传…重新上传取消
-
-
- 查看修改历史
-
在开发过程中可能会经常查看代码的修改历史,或者叫做查看代码的修改日志。用来查看某个版本是谁修改的,什么时间修改的,修改了哪些内容。
可以在文件上点击右键选择“显示日志”来查看文件的修改历史。
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 差异比较
-
当文件内容修改后,需要和修改之前对比一下修改了哪些内容此时可以使用“比较差异功能”
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 还原修改
-
当文件修改后不想把修改的内容提交,还想还原到未修改之前的状态。此时可以使用“还原”功能。
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
注意:此操作会撤销所有未提交的修改,所以当做还原操作是需要慎重慎重!!!
-
- 删除文件
需要删除无用的文件时可以使用git提供的删除功能直接将文件从版本库中删除。
正在上传…重新上传取消
-
- 案例:将java工程提交到版本库
第一步:将参考资料中的java工程project-test复制到工作目录中
正在上传…重新上传取消
第二步:将工程添加到暂存区。
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
点击确定完成暂存区添加。
三、忽略文件或文件夹
在此工程中,并不是所有文件都需要保存到版本库中的例如“bin”目录及目录下的文件就可以忽略。好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
如果使用TortoiseGit的话可以使用菜单项直接进行忽略。
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
选择保留本地文件。完成后在此文件夹内会多出一个.gitignore文件,这个文件就是文件忽略文件,当然也可以手工编辑。其中的内容就是把bin目录忽略掉。
正在上传…重新上传取消
- 提交代码
将代码添加到master分支上,其中.gitignore文件也需要添加到暂存区,然后提交到版本库。
-
- 忽略文件语法规范(了解)
空行或是以 # 开头的行即注释行将被忽略。
可以在前面添加正斜杠 / 忽略当前路径文件,但不包括子目录的同名文件。
可以在后面添加正斜杠 / 来忽略文件夹。
可以使用 ! 来否定忽略,即比如在前面用了 *.apk ,然后使用 !a.apk ,则这个a.apk不会被忽略。
* 用来匹配零个或多个字符,如 *.[oa] 忽略所有以".o"或".a"结尾, *~ 忽略所有以 ~ 结尾的文件(这种文件通常被许多编辑器标记为临时文件); [] 用来匹配括号内的任一字符,如 [abc] ,也可以在括号内加连接符,如 [0-9] 匹配0至9的数; ? 用来匹配单个字符。
看了这么多,还是应该来个栗子:
# 忽略 .a 文件
*.a
# 但否定忽略 lib.a, 尽管已经在前面忽略了 .a 文件
!lib.a
# 仅在当前目录下忽略 TODO 文件, 但不包括子目录下的 subdir/TODO
/TODO
# 忽略 build/ 文件夹下的所有文件
build/
# 忽略 doc/notes.txt, 不包括 doc/server/arch.txt
doc/*.txt
# 忽略所有的 .pdf 文件 在 doc/ directory 下的
doc/**/*.pdf
- 远程仓库
- 添加远程库
现在我们已经在本地创建了一个Git仓库,又想让其他人来协作开发,此时就可以把本地仓库同步到远程仓库,同时还增加了本地仓库的一个备份。
常用的远程仓库就是github:GitHub: Where the world builds software · GitHub,接下来我们演示如何将本地代码同步到github。
-
-
- 在github上创建仓库
-
首先你得在github上创建一个账号,然后在github上创建一个仓库:
正在上传…重新上传取消
正在上传…重新上传取消
点击“create repository”按钮仓库就创建成功了。
正在上传…重新上传取消
Github支持两种同步方式“https”和“ssh”。如果使用https很简单基本不需要配置就可以使用,但是每次提交代码和下载代码时都需要输入用户名和密码。而且如果是公司配置的私有git服务器一般不提供https方式访问,所以我们着重讲“ssh”方式。
-
-
- ssh协议
- 什么是ssh?
- ssh协议
-
SSH是英文Secure Shell的简写形式。通过使用SSH,你可以把所有传输的数据进行加密,这样"中间人"这种攻击方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。
使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替Telnet,又可以为FTP、Pop、甚至为PPP提供一个安全的"通道"。
如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。
最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。
-
-
-
- ssh密钥生成
-
-
在windows下我们可以使用 Git Bash.exe来生成密钥,可以通过开始菜单或者右键菜单打开Git Bash
正在上传…重新上传取消
git bash 执行命令,生命公钥和私钥
命令: ssh-keygen -t rsa
正在上传…重新上传取消
执行命令完成后,在window本地用户.ssh目录C:\Users\用户名\.ssh下面生成如下名称的公钥和私钥:
正在上传…重新上传取消
-
-
-
- ssh密钥配置
-
-
密钥生成后需要在github上配置密钥本地才可以顺利访问。
正在上传…重新上传取消
正在上传…重新上传取消
使用文本编辑器打开刚刚生成的公钥(id_rsa.pub),在key部分将id_rsa.pub文件内容添加进去,然后点击“Add SSH key”按钮完成配置。
-
-
- 同步到远程仓库
- 使用git bash
- 同步到远程仓库
-
在仓库所在的目录(D:\git)点击右键选择“Git Bash Here”,启动git bash程序。
正在上传…重新上传取消
然后在git bash中执行如下语句(参考7.1.1步骤,最后一张图里面的命令):
git remote add origin git@github.com:xuziyijava/mytest.git
git push -u origin master
注意:其中红色字体部分需要替换成个人的用户名。
如果出现如下错误:
正在上传…重新上传取消
可以先执行如下命令,然后再执行上面的命令
$ git remote rm origin
正常的效果:
正在上传…重新上传取消
-
-
-
- 使用TortoiseGit同步
-
-
- 由于TortoiseGit使用的ssh工具是“PuTTY”git Bash使用的ssh工具是“openSSH”,如果想让TortoiseGit也使用刚才生成的密钥可以做如下配置:
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
Url:远程仓库的地址
推送URL:也是相同的
Putty密钥:选择刚才生成的密钥中的私钥
- 同步。在本地仓库的文件夹中单击右键,选择“Git同步”
正在上传…重新上传取消
-
- 从远程仓库克隆
克隆远程仓库也就是从远程把仓库复制一份到本地,克隆后会创建一个新的本地仓库。选择一个任意部署仓库的目录,然后克隆远程仓库。
-
-
- 使用git bash:
-
$ git clone git@github.com:xuziyijava/mytest.git
正在上传…重新上传取消
-
-
- 使用TortoiseGit:
-
在任意目录点击右键:
正在上传…重新上传取消
-
- 从远程仓库取代码
Git中从远程的分支获取最新的版本到本地有这样2个命令:
- git fetch:相当于是从远程获取最新版本到本地,不会自动merge(合并代码)
- git pull:相当于是从远程获取最新版本并merge到本地
上述命令其实相当于git fetch 和 git merge
正在上传…重新上传取消
在实际使用中,git fetch更安全一些,因为在merge前,我们可以查看更新情况,然后再决定是否合并。
如果使用TortoiseGit的话可以从右键菜单中点击“拉取”(pull)或者“获取”(fetch)
正在上传…重新上传取消
-
- 搭建私有Git服务器
- 服务器搭建
- 搭建私有Git服务器
远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。
搭建Git服务器需要准备一台运行Linux的机器,在此我们使用CentOS。以下为安装步骤:
1、安装git服务环境准备
yum -y install curl curl-devel zlib-devel openssl-devel perl cpio expat-devel gettext-devel gcc cc
2、下载git-2.5.0.tar.gz
1)tar -zxf git-2.5.0.tar.gz
2)cd git-2.5.0
3)autoconf
4)./configure
5)make
6)make install
3、添加用户
adduser -r -s /bin/sh -c 'git version control' -d /home/git git
4、设置/home/git文件夹操作权限
mkdir /home/git
chown git:git /home/git
5、设置密码
passwd git
输入两次密码,密码为git
6、切换到git用户
su git
7、创建git仓库
git --bare init /home/git/mygit
注意:如果不使用“--bare”参数,初始化仓库后,提交master分支时报错。这是由于git默认拒绝了push操作,需要.git/config添加如下代码:
[receive]
denyCurrentBranch = ignore
推荐使用:git --bare init初始化仓库。
-
-
- 连接服务器
-
私有git服务器搭建完成后就可以向连接github一样连接使用了,但是我们的git服务器并没有配置密钥登录,所以每次连接时需要输入密码。
使用命令连接:
$ git remote add origin ssh://git@192.168.37.139/home/git/mygit
同步
$ git push -u origin master
这种形式和刚才使用的形式好像不一样,前面有ssh://前缀,也可以这样写:
$ git remote add origin git@192.168.37.139:mygit
使用TortoiseGit同步的话参考上面7.1.3.2的使用方法。
- 分支管理
- 创建合并分支
在我们每次的提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD指针严格来说不是指向提交,而是指向master,master才是指向提交的。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
正在上传…重新上传取消
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
正在上传…重新上传取消
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
正在上传…重新上传取消
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
正在上传…重新上传取消
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
正在上传…重新上传取消
-
- 使用TortoiseGit实现分支管理
- 创建分支
- 使用TortoiseGit实现分支管理
在本地仓库文件夹中点击右键,然后从菜单中选择“创建分支”:
正在上传…重新上传取消
正在上传…重新上传取消
如果想创建完毕后直接切换到新分支可以勾选“切换到新分支”选项或者从菜单中选择“切换/检出”来切换分支:
正在上传…重新上传取消
-
-
- 合并分支
-
分支切换到dev后就可以对工作区的文件进行修改,然后提交到dev分支原理的master分支不受影响。例如我们修改mytest.txt中的内容,然后提交到dev分支。
正在上传…重新上传取消
正在上传…重新上传取消
切换到master分支后还是原理的内容:
正在上传…重新上传取消
将dev分支合并到master分支,当前分支为master。从右键菜单中选择合并
正在上传…重新上传取消
再查看mytest.txt的内容就已经更新了:
正在上传…重新上传取消
-
- 解决冲突
两个分支中编辑的内容都是相互独立互不干扰的,那么如果在两个分支中都对同一个文件进行编辑,然后再合并,就有可能会出现冲突。
例如在master分支中对mytest.txt进行编辑:
正在上传…重新上传取消
然后提交到版本库。
切换到dev分支,对mytest.txt进行编辑:
正在上传…重新上传取消
然后提交到版本库。
最后进行分支合并,例如将dev分支合并到master分支。需要先切换到master分支然后进行分支合并。
正在上传…重新上传取消
出现版本冲突。
正在上传…重新上传取消
冲突需要手动解决,如下图解决完毕:
正在上传…重新上传取消
在冲突文件上单机右键选择“解决冲突”菜单项:
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
把冲突解决完毕的文件提交到版本库就可以了。
- Eclipse客户端egit
- 安装egit插件
Eclipse Mars2版本自带此插件
-
- 提交代码到本地仓库
- 设置使用Git
- 提交代码到本地仓库
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 将工程添加到本地仓库
-
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 设置忽略的文件
-
正在上传…重新上传取消
如下图,加入检入时需要忽略的文件
正在上传…重新上传取消
-
-
- 提交代码到暂存区
-
回到java视图
正在上传…重新上传取消
添加代码到git中
正在上传…重新上传取消
提交代码到本地
正在上传…重新上传取消
正在上传…重新上传取消
-
- Push代码到远程仓库
正在上传…重新上传取消
设置git服务器地址:
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 检入检出远程仓库
-
当第一次检入到git服务器后,后续的代码检入检出git服务器的操作如下图即可。
正在上传…重新上传取消
注意:Commit提交的作用是把代码提交到本地。
Push的作用是把本地的代码提交到远程的git服务器。
-
- 检出代码
- 克隆git仓库到本地
- 检出代码
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 设置git文件存放路径
-
正在上传…重新上传取消
-
-
- 导出工程
-
正在上传…重新上传取消
正在上传…重新上传取消
填写工程名
正在上传…重新上传取消
转换工程为对应的类型
正在上传…重新上传取消
-
- 解决冲突
- 解决代码冲突
- 解决冲突
正在上传…重新上传取消
正在上传…重新上传取消
-
-
- 提交解决冲突后的代码
-
把解决冲突后的代码执行 Add to Index
正在上传…重新上传取消
先Commit到本地
再Push到远程的git服务器
正在上传…重新上传取消
1.1.3开发者请其它同事进行code review-- 4
3 linux下基于gitolite部署Git服务-- 24
3.3.1 git拉下gitolite的安装文件--- 26
3.5.1 克隆gitolite-admin仓库--- 27
Git用户和管理手册
本文档适用于windows用户和linux用户。
0 概述
0.1 Git相关简介
这里主要说明Git、Gitolite、Msysgit、TortoiseGit、Github、Gitlist和Gitlab这几个软件和应用之间的关系以及它们的作用,本文档主要由它们的安装、配置和使用展开的。下图表示的是它们之间的关系:
正在上传…重新上传取消
Git:Git是一项技术,它是一个分布式的版本控制系统,它完全不同于集中式的版本控制系统Svn,至于它们各自的优劣不是这里的重点,要了解Git和Svn的区别请参考文档——Git总结(主要是git和svn的比较和git的一些优点):
正在上传…重新上传取消
Gitolite: Gitolite是一款 Perl 语言开发的 Git 服务管理工具,通过公钥对用户进行认证,并能够通过配置文件对读写操作进行基于分支和路径的的精细授权。
Msysgit:Msysgit是 Git 版本控制系统在 Windows 下的版本。msysGit 有个简单的 GUI 工具,及简单的 Explorer 集成;但它自带的 Bash(命令行式) 非常好用,深得Linux 的真传。
TortoiseGit:TortoiseGit 只是 GUI 工具,使用它需要先安装 MsysGit,这是正宗的 Git 之 Windows 版本。其用法类似于TortoiseSVN。
Github:GitHub可以托管各种git库,并提供一个web界面,它是一个使用Git服务的平台,开源项目免费托管,而私有库并非如此。已经有人将GitHub称为代码玩家的MySpace。
Gitlist: gitlist是一个非常简单好用的web方式代码浏览工具,用php写成。这个只是一个轻量级的代码浏览工具,只是对代码进行浏览,其风格与github也是极其的相似,对于代码的查看也一样具有高亮,支持markdown语法。但是它不能像github或者gitlab一样进行详细的管理。如果只是进行简单的查看使用gitlist非常简单。但是如果是要做一个成熟的代码管理工具,建议使用gitlab。它十分的强大,几乎是github的翻版。
0.2 SSH
SSH 协议用于为 Git 提供远程读写操作,是远程写操作的标准服务,在智能HTTP协议出现之前,甚至是写操作的唯一标准服务。
对于拥有 SHELL 权限的 SSH 登录帐号,可以直接用下面的 git 命令访问,例如:
$ git clone <username>@<server>:/path/to/repo.git
- <username> 是服务器 <server> 上的用户帐号。
- /path/to/repo.git 是服务器中版本库的绝对路径。若用相对路径则相对于 username 用户的主目录而言。
- 如果采用口令认证,不能像 HTTPS 协议那样可以在 URL 中同时给出登录名和口令,必须每次连接时输入。
- 如果采用公钥认证,则无须输入口令。
SSH 协议来实现 Git 服务,有如下方式:
- 其一是用标准的 ssh 帐号访问版本库。即用户帐号可以直接登录到服务器,获得 shell。
- 另外的方式是,所有用户都使用同一个专用的 SSH 帐号访问版本库。各个用户通过公钥认证的方式用此专用 SSH 帐号访问版本库。而用户在连接时使用的不同的公钥可以用于区分不同的用户身份。
1Git使用场景
1.1使用Git合作开发工作流程
开始会准备一个中心git代码库。首先,我们将整理好的代码分模块在git中心库中建立git库。并将文件add到中心库中。 接下来,开发者通过git-clone将代码从中心库clone到本地开发环境。对于较大的项目,我们还建议每个组选择一个负责人,由这个负责人负责从中心库获取和更新最新的代码,其它开发者从这个负责人的git代码库中clone代码。此时,对开发者来说,这个负责人的git库就是中心库了。
1.1.1获取最新代码
开发人员从中心库获取最新的代码:
正在上传…重新上传取消
1.1.2开发者在本地迭代开发
当用户将代码clone到本地后, 就可以进行本地的迭代开发,建议用户不要在master分支上开发,而是建立一个开发分支进行开发。 在本地开发中,用户可以随意的创建临时分支,随意commit。
正在上传…重新上传取消
1.1.3开发者请其它同事进行code review
当本地开发完毕,可以请其它同事进行代码审查。过程为:
正在上传…重新上传取消
1. user2通过git-pull命令,将开发者(user1)的开发分支(dev)pull到user2本地的一个tmp分支,并切换工作分支到该分支上进行code review。
2. 完成code review后, user2切换回其原有开发分支继续开发,并告知user1已经修改完毕。
3. User1将user2的tmp分支git-pull到本地tmp分支,并和dev分支进行merge。最终得到一个code review后的dev分支。
当然,user2也可以直接坐在user1旁边在他的代码上进行review。而不需要走上述步骤。(图中第7步,不是git-pull,而是直接在dev分支上和user1边review边modify)
1.1.4和中心库进行代码合并
使用过svn的人都知道, 在commit之前,都要做一次svn update,以避免和中心库冲突。Git也是如此。现在我们已经经过了code review, 准备向中心库提交变化了, 在开发的这段时间,也许中心库发生了变化, 因此,我们需要在向中心库提交前,再次将中心库的master分支git-pull到本地的master分支上。并且和dev分支做合并。最终,将合并的代码放入master分支。
此外,如果发现合并过程变化非常多, 出于代码质量考虑,建议再做一次code review。下图是他的合并过程:
正在上传…重新上传取消
1.1.5 push代码到中心库
此时,已经完全准备好提交最终的代码了。 通过git-push就可以了。
正在上传…重新上传取消
1.1.6 合作流程总结
我们可以看到,使用git进行合作开发,这一过程和svn有很多相似性,同时,增强了以下几个环节:
1. 开发者在本地进行迭代开发,可以经常的做commit操作且不会影响他人。 而且即使不在线也可以进行开发。只需要最后向中心库提交一次即可。
2. 更有利于在代码提交前做code review。 以往用svn, 都是代码提交后才做code view。如果发生问题, 也无法避免服务器上有不好的代码。 但是用git, 真正向中心库commit前,都是在本地开发,可以方便的进行code review, 然后才提交到中心库。更有利于代码质量。而且, 大家应该可以感到,使用git的过程中,更容易对代码进行code review,因为影响因素更小。
3. 创建多分支,更容易在开发中进行多种工作,而使工作间不会互相影响。 比如user2对user1的代码进行code review时,就可以非常方便的保留当时的开发现场,并切换到user1的代码分支,在code review完毕后,也可以非常方便的切换会曾经被中断的工作现场。
诚然,带来这些好处的同时,确实也使得操作比svn复杂了一些。但我们觉得和前面所能获得的好处相比,这些麻烦是值得的。 当大家用惯了之后会发现,这并不增加多大的复杂性, 而且开发流程会更加自然。请大家多动手,多尝试!
1.2脱离服务器工作
用过SVN的人都知道,在用SVN开发中我们不能离开服务器进行开发,但是Git可以,当你下班回家后突然对白天的某一段代码有了灵感,那么你就可以打开电脑继续工作,看下面的流程图,白天在服务器Git-pull下来的版本库一定存在的,这是你可以新建分支进行开发,在完成添加、修改等操作后,然后进行merge和本地的commit操作,等到第二天连接到电脑时push到服务器的中心库。类似于本地迭代开发。
1.3现场版本控制
所谓现场版本控制,就是在客户现场或在产品部署的现场,进行源代码的修改,并在修改过程中进行版本控制,以便在完成修改后能够将修改结果甚至修改过程一并带走,并能够将修改结果合并至项目对应的代码库中。
因为现场是临时的工作地点,所以没有必要专门的架设一台Git服务器,在一台PC机就可以完成现场版本的控制。
(1)在某一目录下面进行版本库的初始化:
$ git init
(2)添加文件并提交:
$ git add –A
$ git commit -m "initialized"
(3)为初始提交建立一个里程碑:“v1 ”:
$ git tag v1
(4)然后开始在工作区中工作 —— 修改文件,提交:
Git commit –m
(5) 当对修改结果满意,想将工作成果保存带走时,可以通过下面的命令,将从 v1 开始的历次提交逐一导出为补丁文件。转换的补丁文件都包含一个数字前缀,并提取提交日志信息作为文件名,而且补丁文件还提供对二进制文件的支持。
$ git format-patch v1..HEAD
(6)通过邮件将补丁文件发出。当然也可以通过其他方式将补丁文件带走。
$ git send-email *.patch
最后使用git命令将Git版本库和补丁文件导入到要备份的服务器。
1.4异地服务器的同步备份
假如你是一个项目经理,你可能就是项目仓库的管理者(也可能是别人),一般地的为了安全只有管理者可以把本机的仓库push到服务器中,当然根据项目的需要不排除所有人有这样的权限的情况,那么管理者的职责就是备份每天的版本库,方便其他开发人员第二天的克隆。如何让辛苦的工作不会因为笔记本硬盘的意外损坏而丢失?
先做个假设:
我们公司在西安有台git服务器A,其ip是:192.168.0.2
在西安的项目经理的PC机ip是:192.168.0.100 (假设他就是那个仓库管理员)
公司在北京数据中心还有一台托管服务器,ip是:206.221.217.*
其中一台服务器用作Git服务器镜像(因为操作在西安,所以选择西安的那台),一般开发人员写好代码push到项目经理的pc机仓库中,然后由项目经理push到服务器,
同步备份实现过程看下图:
正在上传…重新上传取消
因为西安的Git服务器和异地数据中心北京的 Git托管服务器建立了镜像,所以每当项目经理向公司内网服务器推送的时候,就会自动触发从内网服务器到外网 Git服务器的镜像操作。相当于图 2-1 中的步骤②,步骤②是自动执行的,无须人工干预。图 2-1 中标记为 mirror 的版本库就是Git镜像版本库,该版本库只向用户提供只读访问服务,而不能对其进行写操作(推送)。这样就完成了异地Git库的同步备份。
1.5合并时冲突的解决
Git中很多命令都可能出现冲突,但从根本上来讲,都是merge 和 patch(应用补丁)时产生冲突。而rebase就是重新设置基准,然后应用补丁的过程,所以也会冲突。一般产生冲突的类型有逻辑冲突、内容冲突、树冲突。
1.5.1逻辑冲突
Git自动处理(合并、应用补丁)成功,但是逻辑上是有问题的。比如另外一个人修改了文件名,但我还使用老的文件名,这种情况下自动处理是能成功的,但实际上是有问题的。
又比如,函数返回值含义变化,但我还使用老的含义,这种情况自动处理成功,但可能隐藏着重大BUG。这种问题,主要通过自动化测试来保障。所以最好是能够写出比较完备的自动化测试用例。这种冲突的解决,就是做一次BUG修正。
1.5.2树冲突
文件名修改造成的冲突,称为树冲突。
比如,a用户把文件改名为a.c,b用户把同一个文件改名为b.c,那么b将这两个commit合并时,会产生冲突。
如果最终确定用b.c,那么解决办法如下:
git rm a.c
git rm origin-name.c
git add b.c
git commit
执行前面两个git rm时,会告警“file-name : needs merge”,可以不必理会。
1.5.3内容冲突
两个用户修改了同一个文件的同一块区域,git会报告内容冲突。我们常见的都是这种,下面来看如何解决:
先来模拟一个冲突,假设user1从user2那里克隆了一个版本,开始两人的版本库是一样的,因为是模拟我们就用一个简单文件来说明吧!这个版本库就有一个文件tmp.txt。开始的文件内容是:
正在上传…重新上传取消
User1克隆后给修改了文件内容:
正在上传…重新上传取消
同时呢,user2也在修改了tmp.txt文件内容:
正在上传…重新上传取消
最后user1执行pull操作,把user2的代码拉到本机进行合并,但是执行pull操作时出现了错误:
正在上传…重新上传取消
User1检查发现自己“1+2+3=5”这是很明显的错误,最后手动解决冲突,删除自己的“1+2+3=5”,保留user1的“1+2+3=6”,然后执行commit操作并推到user1的库中。
这就是内容冲突解决的过程。
2 windows下Git的安装
2.1 安装MsysGit
2.1.1 msysgit下载
Git-1.7.3.1-preview20101002.exe下载地址:
2.1.2 msysgit的安装图解
双击.exe文件开始安装:
正在上传…重新上传取消
正在上传…重新上传取消
选择安装路径:
正在上传…重新上传取消
同时安装Git Bash(命令行式)和Git GUI:
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
这一步主要是选择换行风格的,选择第三个Git就不会修改换行风格了:
正在上传…重新上传取消
这样msysgit的安装就算结束了。
2.1.3 使用Git远程克隆一个版本库
双击桌面上的Git图标启动Git程序:
正在上传…重新上传取消
配置全局变量:
git config --global user.name “your name”,比如我的是wanganlei,自行设置。
正在上传…重新上传取消
git config –global user.email “your email”
正在上传…重新上传取消 设置全局变量的目的主要是为了在操作时方便git对你身份的识别和验证。
生成自己的公钥:
正在上传…重新上传取消
生成的公钥的位于你的电脑中“C:\Documents and Settings\Airen\.ssh”的“id_rsa.pub”文件下:
正在上传…重新上传取消
使用记事本打开就能看到相应的信息:
正在上传…重新上传取消
此时只需要将你的公钥放到你项目的服务中就可以进行git的相关操作,如何放入后面会做介绍。比如我已经把我的公钥放入我们办公室的服务器了,现在进行克隆一个版本库下来。
克隆版本库:
Git clone git@[your serverip]/[仓库的绝对路径]
正在上传…重新上传取消
看见没,这样我克隆的仓库就保存在D:/git/test目录下了。仓库克隆到本机我们就能脱离服务器进行工作了,我们可以修改文件、添加文件、目录等,在本地提交以后推到服务器上。
2.1.4 Bash出现错误的解决办法
Ls不能显示中文目录:
解决办法:在git/etc/git-completion.bash中增加一行:
alias ls='ls --show-control-chars --color=auto'
git commit不能提交中文注释:
解决办法:修改git/etc/inputrc中对应的行:
set output-meta on
set convert-meta off
git log无法显示中文注释:
解决办法:在git/etc/profile中增加一行:
export LESSCHARSET=iso8859
2.2 安装TortoiseGit
安装tortoisegit的前提是必须安装了msysgit。如果你是一个linux的爱好者,完全没有必要安装windows下的图形界面TortoiseGit工具,Git Bash的使用绝对的简单方便,但是比如你习惯了TortoiseSvn的使用习惯,那么TortoiseGit和它的使用有点类似,深得windows使用者的追随。
2.2.1 TortoiseGit下载地址
TortoiseGit-1.8.0.0-32bit.zip下载地址:
http://kanboxshare.com/link/Ng0EoXO72Dtg7jPSfY5M3gQMHIUj3WT7N7CdJNVPPMBEngbviX4vbWbM0IdEifszOw3Ua
2.2.2 TortoiseGit的安装过程
TortoiseGit的安装过程比较简单,默认安装即可。
2.2.3 设置
先到TortoiseGit程序组中调用Settings进行设置:
正在上传…重新上传取消
Msysgit的Git.exe的安装路径要加对,默认是 C:\Program Files\Git\bin
正在上传…重新上传取消
如果在Git Bash里面没有设置用户信息,在这里设置即可:
正在上传…重新上传取消
接下来就可以使用TortoiseGit了。
2.3 TortoiseGit的日常用法
2.3.1 创建新库
在文件夹中按右键,选择Git Create repository here就可以创建库了:
正在上传…重新上传取消
在出现的窗口中,不勾选选项,直接按OK:
正在上传…重新上传取消
在目录中就会出现一个名为.git的隐藏文件夹,所有库的相关内容都会存在这个文件夹中.以后不管这个项目添加多少个文件夹,整个库只会有这一个管理文件夹,这和CVS和SVN有较大差异。
2.3.2添加文件夹及其文件
比如我们创建了若干文件夹和文件以后,然后仓库的文件夹里面右键,选
GitCommit->“master”…
这样才算是把文件真正的提交到我们新建的仓库里面了。
正在上传…重新上传取消
正在上传…重新上传取消
接着填写Message,勾选WholeProject选项,这样Commit的时候可以将整个项目的信息全部Commit上去。
2.3.3 创建分支
在有.git的目录中选择TortoiseGit再选CreateBranch…就可以创建分支了。
正在上传…重新上传取消
勾选Switchtonewbranch,就可以跳转到建立好的分支上:
正在上传…重新上传取消
2.2.4 分支的切换
右键选择git branch就能看见该仓库的所有分支,通过鼠标选择进行分支的切换,如下图我们现在的仓库有三个分支,前面打对勾的是当前所在的分支。
正在上传…重新上传取消
2.2.5 查看分支的情况及修改的log
通过选择Showlog,可以看分支情况和修改log:
正在上传…重新上传取消
勾选AllBranches可以看到所有分支的情况:
正在上传…重新上传取消
在Message列中,绿色的是分支,红色的是当前工作分支。
2.2.6 比较版本的差异
通过按Shift和鼠标左键,可以选中两个版本,接着再按鼠标右键,选中Compare revisions,就可以比较两个revision了:
正在上传…重新上传取消
我选中的是branch2和master分支,通过比较发现增加了log.txt:
正在上传…重新上传取消
2.2.7 分支的合并
首先切换到master分支,接着选Merge:
正在上传…重新上传取消
然后选择branch2就可以实现将branch2分支合并到主版本master分支:
正在上传…重新上传取消
到此,TortoiseGit的主要用法讲述完毕,还有其他的功能和应用,请参考相关文档:
Git客户端TortoiseGit软件的安装与使用说明
03-Git客户端TortoiseGit软件的安装与使用说明 - 百度文库
TortoiseGit使用入门
TortoiseGit使用入门_懒虫一个V的博客-优快云博客_tortoisegit 远程
3 linux下基于gitolite部署Git服务
本教程选用的linux系统是centos 6.0。服务器的ip为:10.17.15.162
3.1 基本原理
git的仓库管理是通过gitolite这个开源项目工具来管理的,而他本身也是一个git仓库形式存在。另外,gitolite 采用的是 SSH 协议并且使用 SSH 公钥认证,所以基本上访问仓库就需要公钥的上传。所有的仓库/用户管理都是通过gitolite-admin仓库项目下的/conf/gitolite.conf 文件来配置的,而用户的登录信息是通过往keydir目录下添加公钥实现的。
当管理员更改仓库内容并提交到服务器之后,服务器便有一个事件钩子来处理相关事情,比如建立仓库和用户等。
所以从上面的基本原理,可以大致知道需要做的事情就是安装git,ssh,gitolite,上传管理员的公钥。
3.2 安装前的准备
3.2.1安装基本环境
yum install openssh-server openssh-client perl --默认的是root用户
3.2.2 安装git服务器
yum install git-core
3.2.3创建git服务器管理用户
添加专为git相关操作的用户git:
adduser --system --shell /bin/sh --create-home --home-dir /home/git git
3.2.4创建git仓库存储目录
添加我们的仓库文件夹,进入/home/git 建立文件夹,并授权给git用户(其实这一步骤,gitolite安装时会帮你搞定的):
cd /home/git
mkdir repositories
授权:
chown git:git ./repositories
chown 700 ./repositories
3.3 安装gitolite
因为在前面我们创建了git用户,现在切换过去吧:
su – git
3.3.1 git拉下gitolite的安装文件
git clone git://github.com/sitaramc/gitolite
拉下来后会在当前目录下看到gitolite文件夹吧,那就对了!然后开始安装。
在git用户目录下建立bin文件夹,并将gitolite安装到此目录下面:
mkdir -p $HOME/bin
gitolite/install -to $HOME/bin
如果报错,那就是缺少模块,根据提示少啥就安装啥(请回到root用户来安装哈)。我的错误大概是perl的缺少模块了,那就安装了一下,安装好了回到上面的步骤,直到安装成功:
3.3.2 解决报错
yum install perl-Time-HiRes
安装完毕之后就回到上面继续安装gitolite吧。
那么至此就是安装算完毕,接下来进行gitolite的配置吧。
3.4 配置gitolite
3.4.1 配置gitolite管理员
gitolite是通过ssh协议的公钥管理来实现身份验证的。所以你可以把你本地电脑的公钥上传上去作为默认的管理员来管理所有的配置信息。那好,回到本地电脑生成公钥(当然你也可以直接在服务器上管理,那就在服务器上生成公钥就好了)。
我是在我的个人电脑上配置的,也就是说我可以在本机管理git服务器。在本地电脑上先看看有没有~/.ssh文件夹,如果有说明已经生成过了,没有就执行下面的操作就好了:
ssh-keygen
你再去看看~/.ssh文件下面应该有id_rsa.pub 和 id_rsa两个文件了吧,其中id_rsa是你的私钥要好好保存的,id_rsa.pub是公钥可以给你要访问的服务器的。现在把公钥复制到服务器上吧:
scp ~/.ssh/id_rsa.pub serverUserName@serverHost:/tmp
上面命令当中的serverUserName和serverHost分别是上面服务器对应的用户帐号和地址,这样就把本地的公钥上传到服务器的/tmp目录下面了。
接下来那么我们回到服务器上面来操作了,开始配置gitolite啦,很简单的。
先转到/tmp目录下面把上传上来的id_rsa.pub重命名”你的管理员账号名.pub”。因为gitolite是根据这个文件名来设立帐号的,比如我会命名为admin:
cd /tmp
mv id_rsa.pub admin.pub(重命名)
3.4.2 安装gitolite
然后开始用这个公钥来配置gitolite:(git用户下)
$HOME/bin/gitolite setup -pk admin.pub
就这样安装好了gitolite,你可以进入你的仓库文件home/git/repositories看看,应该增加了两个仓库了文件了gitolite-admin.git 和 test.git。其中前者是管理仓库的,后者是测试用的。
3. 5开始配置管理
因为管理员设为了本机的,那我们现在回到本机来管理试一下吧!
3.5.1 克隆gitolite-admin仓库
git clone git@serverHost:gitolite-admin
这时候就不用git用户的密码了吧,这就是ssh协议作用,然后进入仓库可以看到conf和keydir两个文件夹。其中conf/gitolite.conf就是添加用户/仓库的配置文件,keydir目录下就是放置对应用户的公钥的地方。
先来看看我的配置文件:
正在上传…重新上传取消
这样我就有了一个自己的用户组和仓库了,修改好了直接push到服务器,服务器就会自动创建好对应的仓库和用户了,你就好好享受git之旅吧!
3.5.2 试试能否克隆回来
git clone git@10.17.15.162:myrepos.git //此时若果不出错的话不提示要输入密码的。
大功告成!
4 Gitolite授权详解
Gitolite的授权是通过修改配置文件来进行精细的授权的,文件存放在gitolite-admin.git仓库中,本版本库(gitolite管理版本库)只有 admin 用户有读写和强制更新的权限。
4.1 授权文件详解
下面我们看一个不那么简单的授权文件:
正在上传…重新上传取消
下来详解上面的授权指令:
•第1行,定义了用户组 @admin,包含两个用户 jiangxin 和 wangsheng。
•第3-4行,定义了版本库 gitolite-admin。并指定只有用户 jiangxin 才能够访问,并拥有读(R)写(W)和强制更新(+)的权限。
•第6行,通过正则表达式定义了一组版本库,即在 ossxp/ 目录下的所有版本库。
•第7行,用户组 @admin 中的用户,可以在 ossxp/ 目录下创建版本库。
创建版本库的用户,具有对版本库操作的所有权限。
•第8行,所有用户都可以读写 ossxp 目录下的版本库,但不能强制更新。
•第9行开始,定义的 testing 版本库授权使用了引用授权语法。
•第11行,用户组 @admin 对所有的分支和里程碑拥有读写、重置、添加和删除的授权。
•第12行,用户 junio 可以读写 master 分支。(还包括名字以 master 开头的其他分支,如果有的话)。
•第13行,用户 junio 可以读写、强制更新、创建以及删除 pu 开头的分支。
•第14行,用户 pasky 可以读写 cogito 分支。 (仅此分支,精确匹配)。
4.2 定义用户组和版本库组
在 conf/gitolite.conf 授权文件中,可以定义用户组或者版本库组。组名称以 @ 字符开头,可以包含一个或多个成员。成员之间用空格分开。
•例如定义管理员组:
@admin = wanganlei liming
•组可以嵌套:
@staff = @admin @engineers tester1
·定义版本库组
@pre_project = test_project testing
5 附录
5.1 Gitweb
Gitweb是以网页的形式追踪代码和管理的形式,这样的管理直观、方便。
Linux搭建Gitweb的参考文档:
http://www.xue5.com/Server/Web/660568.html
5.2 Gitlist的搭建
http://www.gitchina.org/?p=397
5.3 GitHub的简单应用
Github是学习和体验git的一个开放平台,这里我们可以Fork好多的开源项目,并克隆到本地,你也可以自己创建项目仓库,与git的爱好者交流学习。
5.3.1 注册用户
注册地址: GitHub: Where the world builds software · GitHub
5.3.2 上传公钥
正在上传…重新上传取消
正在上传…重新上传取消
点击“Add SSH key”后给key命名,然后把本机的id_rsa.pub用记事本打开并复制,粘贴到key框中,最后点击“Add key”,这样我们就能在本机clone和push它上面的任意开源库了。
5.3.3 新建仓库
正在上传…重新上传取消
5.3.4 远程克隆
git clone git@github.com:[username]/[repositories’s name].git
eg.
git clone git@github.com:chinasoftwang/git-test.git