2024年2月3日发(作者:)
Git使用指南LiYanruiv0.1,20080728liyanrui.m2@
前Git是什么言非常简单地说,Git是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。所谓版本控制系统(VersionControlSystem),从狭义上来说,它是软件项目开发过程中用于储存我们所写的代码所有修订版本的软件,但事实上我们可以将任何对项目有帮助的文档交付版本控制系统进行管理。2005年,Torvalds开始着手开发Git是为了作为一种过渡方案来替代BitKeeper,后者之前一直是Linux内核开发人员在使用的版本控制工具,当时由于自由软件社区中的许多人觉得BitKeeper的使用许可证并不适合自由软件社区的工作,因此Linus决定着手开发许可证更为自由灵活的版本控制系统。尽管最初Git的开发是为了辅助Linux内核开发的过程,但是现在很多其他自由软件项目中也使用了Git实现代码版本管理,譬如,项目、许多的项目、Ruby项目等。为什么使用版本控制系统版本控制系统是为懒人准备的,它让懒人们比那些善于备份文档的勤劳人拥有更干净的文件系统以及更多的可以活着的时间。本文档主要内容在第1章中讲述如何使用Git管理自己的个人文档,主要是初步熟悉Git的诸多概念及其日常基本命令的使用。第2章中主要讲述如何基于Git实现多人协作的项目开发模式,以此扭转当前实验室成员在项目研发中各自为政或不能有效沟通的现状。第3章讲述如何利用Git强大的项目分支管理功能实现良好风格的项目协同开发模式。第4章为Git使用之FAQ,用于记载在本实验室推广使用Git过程中诸位同学所遇到的一些细节问题。
Contents第1章使用Git管理个人文档1.11.2何种文档需要保存1.3建立项目仓库1.4关于建立1.5仓库与工作树Git仓库的一些细节1.6在项目中工作1.7查看版本历史1.8撤销与恢复1.9如何使用总结Git帮助文档第2章基于Git的团队协同开发2.12.2两个人如何协同2.3如何解决仓库合并冲突2.4三人以至更多人如何协同2.5M2GE总结的协同开发第3章项目分支管理3.13.2如何产生项目分支3.3分支的合并3.4M2GE总结新的协同开发模式9161617
第1章使用Git管理个人文档本章讲述如何使用Git管理我们的个人文档,用以展示Git的一些基本功能,并且秉承学以致用、用以促学的精神,引导大家积极地将Git应用于日常学习与工作中的文档备份。仿温水煮蛙之古例,此章乃温水也。1.1何种文档需要保存凡需要持续变动的文档皆可作为项目并交付于Git进行管理。由于Git可以详细地记录对于项目的各种修改并提供了功能强大的版本控制,因此愈是修改较为频繁的文档,愈是有必要将其纳入Git的管理之下。理论上,Git可以保存任何文档,但是最善于保存文本文档,因为它本来就是为解决软件源代码(也是一种文本文档)版本管理问题而开发的,提供了许多有助于文本分析的工具。对于非文本文档,Git只是简单地为其进行备份并实施版本管理。1.2建立项目仓库欲使用Git对现有文档进行版本控制,首先要基于现有文档建立项目仓库。下面以本文档的版本管理为例,演示如何将其作为项目并纳于Git的版本控制之下。本文档是由TEX生成的,对应TEX源文档皆位于$HOME/work/m2doc目录下,下文为叙述方便,以Bash变量$WORK代替该目录。首先需初始化Git仓库:$cd$WORK$gitinitGit会作出以下回应:InitializedemptyGitrepositoryin$PROJECT/.git/上述操作的结果是在$WORK目录下创建了一个.git隐藏目录,它就是所谓的Git仓库,不过现在它还是空的。另外$WORK目录也不再是普通的文档目录了,今后我们将其称为工作树。
下面应当有选择地将工作树中的一些文档存储至Git仓库中。由于Git在向仓库中添加文档时并非是简单地文档复制过去,势必要将所添加文档进行一番处理,生成Git仓库所能接受的数据格式,Git称这个过程为"takeasnapshot"(生成快照)。若将工作树下所有文档(包含子目录)生成快照,可采用以下命令:$cd$WORK$gitadd.所生成的快照被存放到一个临时的存储区域,Git称该区域为索引。使用git-commit命令可将索引提交至仓库中,这个过程称为提交,每一次提交都意味着版本在进行一次更新。git-commit最简单的用法如下:$gitcommit执行上述git-commit命令时,Git会自动调用系统默认的文本编辑器,要求你输入版本更新说明并保存。请记住,输入简约的版本更新说明是非常有必要的,它就像剧本一样,可以帮助你快速回忆起对项目的重大改动。对于简短的版本更新信息,可以使用git-commit的“-m”选项,如下:$gitcommit-m"你的版本更新信息"上述过程即为建立Git仓库的一般过程,我将其总结为图1.1所示之流程:版本更新说明git-init仓库初始化git-add生成快照并存入项目索引git-commit项目索引提交图1.1Git仓库建立流程2
1.3关于建立Git仓库的一些细节看过上一节内容,也许你会跃跃欲试,准备拿自己的一个文档目录下手。切莫如此着急,为了概念的完整性,上一节内容中,我故意省略了两个细节问题,下面逐一道来。第一个问题是:在使用Git之前,你需要面对Git来一番自我介绍。Git不喜欢不愿透漏姓名的人,因为它要求每个人在向仓库提交数据时,都应当承担一定的责任。要向Git进行自我介绍,请使用以下命令:$"YourNameComesHere"$ou@第二个问题是:在生成文档内容快照时,工作树中有一些文档是你不希望接受Git管理的,譬如程序编译时生成的中间文件,对于这样的文件如何避免为之生成快照?譬如对于上一节的用例,在工作树中存在以下文件(或子目录):其中的zh目录存放着TEX文档编译时生成的中间文件,因此该目录不应该被Git所管理。为解决此类问题,Git提供了文档忽略机制,可以将工作树中你不希望接受Git管理的文档信息写到同一目录下的.gitignore文件中。对于本例中的zh目录,采用如下操作可将其排除仓库之外,然后再对$WORK生成快照即可。$cd$WORK$echo"zh">.gitignore$gitadd.有关gitignore文件的诸多细节知识可阅读其使用手册:$mangitignore3
1.4仓库与工作树按照前文的说法,Git仓库就是那个.git目录,其中存放的是我们所提交的文档索引内容,Git可基于文档索引内容对其所管理的文档进行内容追踪,从而实现文档的版本控制。工作树是包含.git的目录,在前文示例中即$WORK目录。为了更加明确仓库与工作树的概念,下面做一个实验:$cp-R$WORK/.git/tmp/$cd/tmp$2doc-copy首先,我们将$WORK目录中的.git目录复制到/tmp目录下并进行重命名为,然后使用git-clone命令1从中生成m2doc-copy目录。若进入m2doc-copy目录观察一下,就会发现该目录所包含的内容是等同于$WORK目录的。上述实验意味着,只要我们拥有仓库,即,那么就可以很容易地生成工作树,而这个工作树又包含着一个仓库,即m2doc-copy/.git。所以,我们可以这样理解:在Git中,仓库与工作树之间无需分的很清楚。1.5在项目中工作在工作树中,我们日常所进行的工作无非是对Git仓库所管理的文档进行修改,或者添加/删除一些文件。这些操作与采用Git管理我们的文档之前没有任何差异,只是在你认为一个工作阶段完成之时,要记得通知Git,命令它记下你所进行更新,这一步骤是通过生成文档快照并将其加入到索引中来实现的。譬如今天,我向$WORK目录添加了一份新文档,我需要通知Git记住我的这一更新:$cd$WORK$1工作树克隆命令,在后文中将会对其详细讲述。4
这样,Git就会将有关的更新添加到索引中。然后我又对其它文档进行了一些修改,譬如修改了以及文件,继续使用git-add命令将它们的更新添加到索引中:$晚上,这一天的工作告以段落,我觉得有必要将今天所做的提交到仓库中,于是执行git-commit操作,将索引内容添加到仓库中。可能一天下来,你对工作树中的许多文档都进行了更新(文档添加、修改、删除),但是我忘记了它们的名字,此时若将所做的全部更新添加到索引中,比较轻省的做法就是:$cd$WORK$gitadd.$输入日志信息...git-add命令通常能够判断出当前目录(包括其子目录)下用户所添加的新文档,并将其信息追加到索引中。git-commit命令的-a选项可将所有被修改的文档或者已删除的文档的当前状态提交倒仓库中。记住,如果只是修改或者删除了已被Git管理的文档,是没必要使用git-add命令的。本节并未讲述新的Git命令,完全是前面所讲过的一些命令的重复介绍,只是它们出现的场景有所区别而已。另外,要注意的问题是,Git不会主动记录你对文档进行的更新,除非你对它发号施令。1.6查看版本历史在工作树中,使用git-log命令可以查看当前项目的日志,也就是你在使用git-commit向仓库提交新版本时所属如的版本更新信息。$gitlog如果你想看一下每一次版本的大致变动情况,可使用以下命令:5
$gitlog--stat--summary下面分析一下git-log命令的回应信息。譬如当我在“Git使用指南”这一文档项目的工作树中查阅项目日志,git-log命令给出了以下回应信息:commitdfb02e6e4f2f7b573337763e5c0013802e392818Author:LiYanrui
每一个项目版本号通常都对应存在一个父版本号,也就是项目的前一次版本状态。可使用如下命令查看当前项目版本的父版本更新细节:$gitshowHEAD^$gitshowHEAD^^$gitshowHEAD~4#查看HEAD的父版本更新细节#查看HEAD的祖父版本更新细节#查看HEAD的祖父之祖父的版本更新细节你可以对项目版本号进行自定义,然后就可以使用自定义的版本号查看对应的项目版本更新细节:$gittagv0.1dfb02$gitshow实际上,上述命令并非是真正的进行版本号自定义,只是制造了一个tag对象而已,这在进行项目版本对外发布时比较有用。本文档后续章节会对tag的一些细节进行介绍。1.7撤销与恢复版本控制系统的一个重要任务就是提供撤销和恢复某一阶段工作的功能。git-reset命令就是为这样的任务而准备的,它可以将项目当前版本定位到之前提交的任何版本中。git-reset命令有三个选项:--mixed、--soft和--hard。我们在日常使用中仅使用前两个选项;第三个选项由于杀伤力太大,容易损坏项目仓库,需谨慎使用。--mixed是git-reset的默认选项,它的作用是重置索引内容,将其定位到指定的项目版本,而不改变你的工作树中的所有内容,只是提示你有哪些文件还未更新。--soft选项既不触动索引的位置,也不改变工作树中的任何内容,但是会要求它们处于一个良好的次序之内。该选项会保留你在工作树中的所有更新并使之处于待提交状态。关于git-reset命令的具体如何使用可留作本章的练习题,你可以随便创建一个Git仓库并向其提交一些版本更新,然后测试--mixed与--soft选项的效果。如果欲查看git-reset命令对工作树的影响,可使用git-status命令。另外,这道练习7
题应当结合git-reset的使用帮助(参考下一节)来做,当你大致明白了git-reset的用法,这道题就算做对了。1.8如何使用Git帮助文档前文中,我一直没有解释这样一个现象,那就是在正文中,总是使用类似git-reset这样的命令形式,但是在终端中实际输入这些指令时,所采用的命令形式又变为gitreset。我猜测这样做的原因是后者作为命令形式对于用户更为友好一些,因为我们已经习惯了在终端中输入这样的命令格式。但是在查阅命令的说明文档时,需要使用第一种命令格式,譬如要查看gitreset命令的用法,可:$mangit-reset1.9总结现在我们总算是掌握了有关Git的一些粗浅但非常实用的知识,已具备了使用Git管理个人文档的能力,希望大家能够学以致用,积极地使用Git来管理你认为需要进行版本控制的个人文档。8
第2章基于Git的团队协同开发很多时候我们是多个人同时为做一件事情而努力,如何有效化解多人协同运作过程中出现的种种矛盾是相当重要的。实践证明,Git可以很好的胜任此类任务,这也是我们要在实验室内部推广Git应用的主要原因。2.1两个人如何协同Lyr与Tzc是本节的两位主角。现在假设Lyr开始着手开发M2GE库,并按照第1章所讲述的Git基本用法将M2GE库纳于Git的管理之下。但是,很快Lyr就发现了仅凭个人之力很难在项目规定期限内完成这项工作,因此他邀请Tzc来参与M2GE库,故事就这样开始了。Lyr的M2GE工作树为/work/m2ge,Tzc可通过以下命令获得与Lyr同样的工作树:$cdwork$gitclonelyr@192.168.0.7:~/work/m2gem2gegit-clone可利用各种网络协议访问远端机器中的Git仓库,从中导出完整的工作树到本地。在上述示例中,Tzc通过SSH协议访问了Lyr机器上的lyr账户的M2GE仓库并进行导出,从而在当前目录下建立了m2ge工作树。若上述命令中未指定本地工作树名,那么git-clone会在Tzc当前所在目录中建立与Lyr的M2GE工作树同名的工作树,所以上述命令指定Tzc的工作树名为m2ge显得有些多余。注意,git-clone命令只要碰到类似以下格式的远端仓库地址,它就会认为该地址是符合SSH协议的。账户@IP:工作树路径Tzc既已获得M2GE工作树,他就可以开始工作了,同时,Lyr也在位于自己的机器上的M2GE工作树中工作。在此期间,二人对位于各自机器上的M2GE仓库的操作只需具备第1章所讲述的内容足矣。
一个阶段之后,二人均将所做的工作不断地提交到各自的Git仓库中,直至他们觉得有必要将各自所做的工作合并起来之后再进行新的开发阶段。由于Lyr作为主要开发者,二人的工作在他的机器上进行合并是比较自然的。当然在Tzc机器上合并也未尝不可,因为Git是不分主次仓库的,同一项目的不同仓库都是地位均等。为实现与Tzc的工作合并,Lyr执行了以下操作:$cd~/work/m2ge$gitpulltzc@192.168.0.5:~/work/m2gegit-pull命令可将属于同一项目的远端仓库与同样属于同一项目的本地仓库进行合并,它包含了两个操作:从远端仓库中取出更新版本,然后合并到本地仓库。上述命令可在Lyr的m2ge仓库中完成对Tzc机器上的myge仓库的合并。如果Lyr与Tzc是对了不同的文件进行了改动,那么可以不费周折地完成仓库合并。但是倘若二人对一些相同的文件进行了改动,那么在合并时必然会遭遇合并冲突的问题,此时手动修改发生合并冲突的文件,然后将结果提交到本地仓库。由于处理合并冲突的问题比较复杂一些,所以下面单独拿出一个小节来讲述。当项目合并结束后,意味着Lyr与Tzc一个协同开发周期的结束,他们彼此很欣赏对方的工作,所以又开始了下一个周期……2.2如何解决仓库合并冲突现在假设Lyr与Tzc在各自的工作树中对同一份文件进行了修改,而原内容如下:onetwothreeLyr对进行了如下改动,并将该改动提交到本地仓库。ONEtwothree10
Tzc对进行了以下改动,也将该改动提交到本地仓库。onetwoTHREE当Lyr在合并Tzc的Git仓库时,Git会自动合并二人对的修改:ONEtwoTHREE现在Lyr工作树中的文件即包含了Lyr的改动,也包含了Tzc的改动,而且合并结果自动作为新版本提交到Lyr的仓库中。观察上述合并冲突示例,可以看出,虽然Lyr与Tzc是对同一份文件进行了修改,但是他们的修改并未重叠。现在假设二人对的同一行做出了修改,那么在仓库合并时会发生什么,应当如何处理呢?现在假定上述示例中,Tzc对的修改如下:oneONEtwothree这样,二人对的同一行进行了不同的修改,当合并时,Git会给出以下反馈信息:FLICT(content):MergeconflictinfooAutomaticmergefailed;fixconflictsandthencommittheresult.上述信息之意是:尝试合并文件的改动发生了冲突,自动合并失败,请用户手动修复冲突然后将结果提交到仓库中。Lyr看到上述信息,就打开了合并后的,他看到了以下内容:11
<<<<<<
$gitclonelyr@192.168.0.7:~/项目开发...$gitadd改动的文件$解决版本合并问题...$gitpush在一个协同周期内,Lyr对M2GE仓库的管理工作相当于管理一份他个人项目一般,因为M2GE库是位于他的机器上,他是不需要git-pull与git-push的。这样,一个基于Git较为简单的三人以至更多人的协同工作模式被实现了,这是我们在尚未熟悉Git应用之时比较稳妥的协同方案。下一节将基于这一方案讲述M2GE库仓库的建立以及多人协同开发过程的具体实现。2.4M2GE的协同开发上一节所给出的三人及三人以上的协同工作模式有些不合理,譬如Lyr过于特殊,别人都要git-pull与git-push,唯独他不需要。现在要剥夺他的这一特权,最有效的办法就是将M2GE仓库建立在实验室的服务器上。首先,Lyr通过SSH登录到服务器,寻找合适位置,建立目录,譬如/project/,然后初始化一个空仓库,以此作为M2GE仓库:$mkdir-p~/project/$cd~/project/$git--bareinit--shared上述操作中,git-init命令的--bare选项可以让目录等价于一个仓库。也就是说,本来是一个工作树,但是--bare选项将本应当存放在/.git中的仓库内容全部放置在目录下,就好像仓库完全的裸露在工作树中,所以称之为赤裸的仓库。然后,Lyr将自己机器上已经接受Git管理的m2ge仓库推送到服务器端的仓库:$cd~/work/m2ge$gitpushm2@192.168.0.2:~/project/ter13
上述git-push命令中出现的master参数的含义将在下一章讲述,此处可略过不谈。现在,大家已经得到了M2GE仓库的最初版本,并且可以使用git-clone命令在本地创建工作目录:$gitclonem2@192.168.0.2:~/project/之后,我们就可以开始一个又一个协同周期,服务器上的仓库将会逐次记录着每位协同开发者的版本更新提交,此基本过程可参考上一节所述内容来理解。2.5总结本章讲述了基于Git最基本的多人协同工作模式,并引入了三个新的Git命令:git-clone、git-pull与git-push。基于这三个命令并配合上一章所讲述Git基本操作,足以实现M2GE初级阶段的协同开发。14
第3章项目分支管理Git最为世人称道的就是它那强大的项目分支管理功能,现在较为流行的版本控制系统,诸如CVS、SVN等,虽然也提供了项目分支管理功能,但是可用性极低。对于Git而言,管理多个项目分支如探囊取物耳。本章主要讲述Git的项目分支管理的基本知识以及如何利用这一功能形成更有章法的项目协同开发模式。3.1如何产生项目分支前两章所讲内容未有提及项目分支问题,但事实上是有一个分支存在的,那就是master分支(主分支),该分支是由Git自动产生的。在此之前,我们针对项目版本的各种操作都是在主分支上进行的,只是我们未察觉它的存在而已。Git可以轻松地产生新的项目分支,譬如下面操作可添加一个名曰“local”的新的项目分支:$gitbranchlocal对于新产生的local分支,初始时是完全等同于主分支的。但是,在local分支所进行的所有版本更新工作都不影响主分支,这意味着作为项目的参与者,可以在local中开始各种各样的更新尝试。查看项目仓库中存在多少分支,可直接使用git-branch命令,譬如使用该命令查看我的M2Doc项目分支列表:$gitbranchlocal*master在上述操作输出结果中,若分支名之前存在*符号,表示此分支为当前分支。其实Git各分支不存在尊卑之别,只存在哪个分支是当前分支的区别。为了某种良好的秩序,很多人默认是将master分支视为主分支,本文也将沿用这一潜在规则。由上述操作输出的分支列表可以看出,虽然使用git-branch命令产生了local分支,但是Git不会自动将当前分支切换到local下。可使用git-checkout命令实现分支切换,下面操作将当前分支切换为前文所产生的local分支:
$gitcheckoutlocal3.2分支的合并我们产生了local分支,并在该分支下进行了诸多修改与数次的版本更新提交,但是该如何将这一分支的最终状态提交到master分支中呢?git-merge命令可实现两个分支的合并。譬如我们将local分支与master分支合并,操作如下:$gitcheckoutmaster$gitmergelocal#将当前分支切换为master#将local分支与当前分支合并当一个分支检查无误并且与master分支成功合并完毕后,那么这一分支基本上就没有存在的必要性了,可以删除掉:$gitbranch-dlocal注意,git-branch的-d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想不问青红皂白地删除一个分支,可以使用git-branch的-D选项。3.3M2GE新的协同开发模式现在来讨论一下如何基于Git项目分支管理功能实现更为稳健、高效的M2GE库的协同开发机制。1现在以Lyr作为主角,看一看他围绕实验室服务器上已经建立了M2GE仓库。M2GE开发工作的一天中的工作过程。首先,Lyr需要更新自己机器上的工作树,并查看实验室其他成员的版本更新信息:$gitpull$gitlog1如有不解,请阅读第2章。16
然后,Lyr开始建立一个新的项目分支,将其命名为lyr,并将当前分支切换为该分支:$gitbranchlyr$gitcheckoutlyr然后这一天中剩余的大部分时间,Lyr都在自己所建立的项目分支上工作,譬如增加了3个新的接口及相关测试程序,并对原有接口做了一些修改。一天的工作完成后,他有必要将这一天的工作与M2GE仓库的master分支进行合并,然后删除lyr分支:$gitcheckout$gitmergelyr$gitbranch-dlyr现在,Lyr已经将这一天的工作反映到自己机器上的M2GEmaster分支上了,他最后要做的是将其推送到服务器的M2GE仓库,以使项目其他成员能够分享他的工作。这里要注意,在推送版本更新之前,需要使用git-pull命令将这一天中其他成员对服务器端的M2GE的更新拉过来合并到自己的master分支,然后才可以将自己的版本更新推送到服务器上的M2GE仓库,具体操作如下:1.使用git-pull命令更新本地工作树;2.若出现版本合并冲突,并且Git无法自动合并,需要手工合并,然后将合并结果提交到本地master分支;3.使用git-push命令将本地master分支更新推送到服务器M2GE仓库中。目前,对于我们而言,在基于Git的M2GE协同开发过程中,引入分支管理功能,可有效防止因个人操作不当而导致向服务器M2GE仓库提交太多的脏数据。另外,也有效保持了本地项目主分支的干净,避免了频繁git-clone服务器端的M2GE仓库来恢复本地的项目主分支。3.4总结本章讲述了Git项目分支管理的基本知识,并利用这些知识巩固了M2GE库的协同开发机制。至此为止,诸位同学已经接触了Git的主要功能,并且已经具备了17
向专业级别的开发团队过渡的基本能力。但是,工具毕竟是工具,并不能代替人的地位,因此希望大家能够学以致用,积极妥善地在日常学习与工作中使用Git,并且努力培养团队协同开发意识。18
本文发布于:2024-02-03 19:58:46,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170696152651138.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |