GIT之学习笔记

一、GTI定义

    Git是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。所谓版本控制系统(Version Control System),从狭义上来说,它是软件项目开发过程中用于储存我们所写的代码所有修订版本的软件,但事实上我们可以将任何对项目有帮助的文档交付版本控制系统进行管理。

    Git是用来代替BitKeeper(Linux内核开发人员在使用的版本控制工具)。

版本控制系统是为懒人准备的,它让懒人们比那些善于备份文档的勤劳人拥有更干净的文件系统以及更多的可以活着的时间。

二、使用Git管理个人文档

    需要保存的文档的类型:凡需要持续变动的文档皆可作为项目并交付于Git 进行管理。由于Git 可以详细地记录对于项目的各种修改并提供了功能强大的版本控制,因此愈是修改较为频繁的文档,愈是有必要将其纳入Git 的管理之下。

    理论上,Git 可以保存任何文档,但是最善于保存文本文档,因为它本来就是为解决软件源代码(也是一种文本文档)版本管理问题而开发的,提供了许多有助于文本分析的工具。对于非文本文档,Git 只是简单地为其进行备份并实施版本管理。

建立项目仓库:

初始化Git仓库:

$ cd $WORK

$ git init

上述操作的结果是在$WORK 目录下创建了一个.git 隐藏目录,它就是所谓的Git 仓库,不过现在它还是空的。另外$WORK 目录也不再是普通的文档目录了,今后我们将其称为工作树。

下面应当有选择地将工作树中的一些文档存储至Git 仓库中。由于Git 在向仓库中添加文档时并非是简单地文档复制过去,势必要将所添加文档进行一番处理,生成Git 仓库所能接受的数据格式,Git 称这个过程为"take a snapshot(" 生成快照)。若将工作树下所有文档(包含子目录)生成快照,可采用以下命令:

$ cd $WORK

$ git add .

所生成的快照被存放到一个临时的存储区域,Git 称该区域为索引。使用git-commit 命令可将索引提交至仓库中,这个过程称为提交,每一次提交都意味着版本在进行一次更新。git-commit 最简单的用法如下:

$ git commit

执行上述git-commit 命令时,Git 会自动调用系统默认的文本编辑器,要求你输入版本更新说明并保存。请记住,输入简约的版本更新说明是非常有必要的,它就像剧本一样,可以帮助你快速回忆起对项目的重大改动。

对于简短的版本更新信息,可以使用git-commit 的“-m”选项,如下:

$ git commit -m "你的版本更新信息"

三、关于建立Git 仓库的一些细节

    第一个问题是:在使用Git 之前,你需要面对Git 来一番自我介绍。Git 不喜欢不愿透漏姓名的人,因为它要求每个人在向仓库提交数据时,都应当承担一定的责任。

    要向Git 进行自我介绍,请使用以下命令:

$ git config --global user.name "Your Name Comes Here"

$ git config --global user.email you@yourdomain.example.com

    第二个问题是:在生成文档内容快照时,工作树中有一些文档是你不希望接受Git 管理的,譬如程序编译时生成的中间文件,对于这样的文件如何避免为之生成快照?

譬如对于上一节的用例,在工作树中存在以下文件(或子目录):

doc-env.tex  git-tutor.tex  Makefile zh

git-tutor  main.tex  vfonts.tex

    其中的zh 目录存放着TEX 文档编译时生成的中间文件,因此该目录不应该被Git 所管理。为解决此类问题,Git 提供了文档忽略机制,可以将工作树中你不希望接受Git 管理的文档信息写到同一目录下的.gitignore 文件中。对于本例中的zh 目录,采用如下操作可将其排除仓库之外,然后再对$WORK 生成快照即可。

$ cd $WORK

$ echo "zh" > .gitignore

$ git add .

四、仓库与工作树

    Git 仓库就是那个.git 目录,其中存放的是我们所提交的文档索引内容,Git 可基于文档索引内容对其所管理的文档进行内容追踪,从而实现文档的版本控制。工作树是包含.git 的目录,在前文示例中即$WORK 目录。

五、在项目中工作

    在工作树中,我们日常所进行的工作无非是对Git 仓库所管理的文档进行修改,或者添加/删除一些文件。这些操作与采用Git 管理我们的文档之前没有任何差异,只是在你认为一个工作阶段完成之时,要记得通知Git,命令它记下你所进行更新,这一步骤是通过生成文档快照并将其加入到索引中来实现的。

    譬如今天,我向$WORK 目录添加了一份新文档ch1.tex ,我需要通知Git 记住我的这一更新:

$ cd $WORK

$ git add ch1.tex

    这样,Git 就会将有关ch1.tex 的更新添加到索引中。然后我又对其它文档进行了一些修改,譬如修改了doc-env.tex 以及git-tutor.tex 文件,继续使用git-add 命令将它们的更新添加到索引中:

$ git add doc-env.tex git-tutor.tex

    晚上,这一天的工作告以段落,我觉得有必要将今天所做的提交到仓库中,于是执行git-commit 操作,将索引内容添加到仓库中。

    可能一天下来,你对工作树中的许多文档都进行了更新(文档添加、修改、删除),但是我忘记了它们的名字,此时若将所做的全部更新添加到索引中,比较轻省的做法就是:

$ cd $WORK

$ git add .

$ git commit -a

... 输入日志信息...

六、查看版本历史

$ git log

如果你想看一下每一次版本的大致变动情况,可使用以下命令:

$ git log --stat --summary

$ git show dfb02e6e4f2f7b573337763e5c0013802e392818

除了使用完整的版本号查看项目版本更新细节之外,也还可以使用以下方式:

$ git show dfb02 # 一般只使用版本号的前几个字符即可

$ git show HEAD # 显示当前分支的最新版本的更新细节

$ git show HEAD^ # 查看HEAD 的父版本更新细节

$ git show HEAD^^ # 查看HEAD 的祖父版本更新细节

$ git show HEAD~4 # 查看HEAD 的祖父之祖父的版本更新细节

七、撤销与恢复

git-reset 命令就是为这样的任务而准备的,它可以将项目当前版本定位到之前提交的任何版本中。

git-reset 命令有三个选项:--mixed 、--soft 和--hard 。我们在日常使用中仅使用前两个选项;第三个选项由于杀伤力太大,容易损坏项目仓库,需谨慎使用。

--mixed 是git-reset 的默认选项,它的作用是重置索引内容,将其定位到指定的项目版本,而不改变你的工作树中的所有内容,只是提示你有哪些文件还未更新。

--soft 选项既不触动索引的位置,也不改变工作树中的任何内容,但是会要求它们处于一个良好的次序之内。该选项会保留你在工作树中的所有更新并使之处于待提交状态。

八、基于Git 的团队协同开发

两个人如何协同

    Lyr 与Tzc 是本节的两位主角。现在假设Lyr 开始着手开发M2GE 库,并按照第1 章所讲述的Git 基本用法将M2GE 库纳于Git 的管理之下。但是,很快Lyr就发现了仅凭个人之力很难在项目规定期限内完成这项工作,因此他邀请Tzc来参与M2GE 库,故事就这样开始了。Lyr 的M2GE 工作树为/work/m2ge ,Tzc 可通过以下命令获得与Lyr 同样的工作树:

$ cd work

$ git clone lyr@192.168.0.7:~/work/m2ge m2ge

    git-clone 可利用各种网络协议访问远端机器中的Git 仓库,从中导出完整的工作树到本地。

    注意,git-clone 命令只要碰到类似以下格式的远端仓库地址,它就会认为该地址是符合SSH 协议的。

账户@IP:工作树路径

    一个阶段之后,二人均将所做的工作不断地提交到各自的Git 仓库中,直至他们觉得有必要将各自所做的工作合并起来之后再进行新的开发阶段。由于Lyr作为主要开发者,二人的工作在他的机器上进行合并是比较自然的。当然在Tzc机器上合并也未尝不可,因为Git 是不分主次仓库的,同一项目的不同仓库都是地位均等。

    为实现与Tzc 的工作合并,Lyr 执行了以下操作:

$ cd ~/work/m2ge

$ git pull tzc@192.168.0.5:~/work/m2ge

    git-pull 命令可将属于同一项目的远端仓库与同样属于同一项目的本地仓库进行合并,它包含了两个操作:从远端仓库中取出更新版本,然后合并到本地仓库。上述命令可在Lyr 的m2ge 仓库中完成对Tzc 机器上的myge 仓库的合并。

<<<<<<< HEAD:foo

ONE

=======

one ONE

>>>>>>> 1116d3270764d91a25532a753a47b8b0e1b6f1b8:foo

two

three

    以一串< 开头的字串表示Lyr 的当前项目版本对foo.txt 的修改结果,而以一串> 开头的字串表示Tzc 的当前项目版本对foo.txt 的修改结果。中间用了一串= 号将二人修改结果隔开。一旦理解了版本冲突的表示格式,Lyr 就很容易地根据现实情况将合并冲突问题解决掉,他认为Tzc 的改动是不符合项目需求的,并且按照项目的实际需求进行了手工合并。最后,Lyr 将合并处理结果提交到仓库中,即完成了重叠冲突的合并问题的解决。

九、三人以至更多人如何协同

    前文在讲述二人协同模式时,强调了Lyr 与Tzc 的主次关系,这种关系似乎对于三人以至更多人的协同也有效。现在我们再引入两位故事主角Lxc 与Zhu 来说明此问题。假设Lxc 与Zhu 仿照Tzc 那样从Lyr 那里git-clone 了一份项目仓库,进行了一番卓有成效的版本更新。最后,Lyr 需要一一取回其他三人的仓库,然后再一一合并方能完成一个协同周期,这些工作逐渐让Lyr 汗流浃背,疲于应付。因此

Lyr 希望其他三人能够分担一下项目版本合并问题的处理工作。

Git 提供了git-pull 的对偶命令,即git-push。顾名思义,git-pull 命令负责从

远端仓库取回版本更新,而git-push 可将本地版本更新推送到远端仓库中。

利用git-pull 与git-push 命令,那么在一个协同周期之内,除了Lyr 之外,其余三人的项目开发流程大致如下:

$ git clone lyr@192.168.0.7:~/work/m2ge

... 项目开发...

$ git add 改动的文件

$ git commit

$ git pull

... 解决版本合并问题...

$ git push

十、M2GE 的协同开发

    上一节所给出的三人及三人以上的协同工作模式有些不合理,譬如Lyr 过于特殊,别人都要git-pull 与git-push,唯独他不需要。现在要剥夺他的这一特权,最有效的办法就是将M2GE 仓库建立在实验室的服务器上。

    首先,Lyr 通过SSH 登录到服务器,寻找合适位置,建立m2ge.git 目录,譬如/project/m2ge.git ,然后初始化一个空仓库,以此作为M2GE 仓库:

$ mkdir -p ~/project/m2ge.git

$ cd ~/project/m2ge.git

$ git --bare init --shared

    上述操作中,git-init 命令的--bare 选项可以让m2ge.git 目录等价于一个仓库。也就是说,m2ge.git 本来是一个工作树,但是--bare 选项将本应当存放在m2ge.git/.git 中的仓库内容全部放置在m2ge.git 目录下,就好像仓库完全的裸露在工作树中,所以称之为赤裸的仓库。

    然后,Lyr 将自己机器上已经接受Git 管理的m2ge 仓库推送到服务器端的m2ge.git 仓库:

$ cd ~/work/m2ge

$ git push m2@192.168.0.2:~/project/m2ge.git master

十一、项目分支管理

    Git 最为世人称道的就是它那强大的项目分支管理功能,现在较为流行的版本控制系统,诸如CVS、SVN 等,虽然也提供了项目分支管理功能,但是可用性极低。对于Git 而言,管理多个项目分支如探囊取物耳。

    如何产生项目分支:

    前面所讲内容未有提及项目分支问题,但事实上是有一个分支存在的,那就是master 分支(主分支),该分支是由Git 自动产生的。在此之前,我们针对项目版本的各种操作都是在主分支上进行的,只是我们未察觉它的存在而已。

Git 可以轻松地产生新的项目分支,譬如下面操作可添加一个名曰“local”的新的项目分支:

$ git branch local

    对于新产生的local 分支,初始时是完全等同于主分支的。但是,在local 分支所进行的所有版本更新工作都不影响主分支,这意味着作为项目的参与者,可以在local 中开始各种各样的更新尝试。

查看项目仓库中存在多少分支,可直接使用git-branch 命令,譬如使用该命令查看我的M2Doc 项目分支列表:

$ git branch

local

* master

    在上述操作输出结果中,若分支名之前存在* 符号,表示此分支为当前分支。其实Git各分支不存在尊卑之别,只存在哪个分支是当前分支的区别。为了某种良好的秩序,很多人默认是将master 分支视为主分支,本文也将沿用这一潜在规则。

    由上述操作输出的分支列表可以看出,虽然使用git-branch 命令产生了local 分支,但是Git 不会自动将当前分支切换到local 下。可使用git-checkout命令实现分支切换,下面操作将当前分支切换为前文所产生的local 分支:

$ git checkout local

十二、分支的合并

    我们产生了local 分支,并在该分支下进行了诸多修改与数次的版本更新提交,但是该如何将这一分支的最终状态提交到master 分支中呢?

    git-merge 命令可实现两个分支的合并。譬如我们将local 分支与master 分支合并,操作如下:

$ git checkout master # 将当前分支切换为master

$ git merge local # 将local分支与当前分支合并

    当一个分支检查无误并且与master 分支成功合并完毕后,那么这一分支基本上就没有存在的必要性了,可以删除掉:

$ git branch -d local

    注意,git-branch 的-d 选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想不问青红皂白地删除一个分支,可以使用git-branch 的 -D 选项。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值