如何快速入门Git应用?(文末福利)

点击标题下「异步社区」可快速关注

本文是专门为Git初学者和高级用户撰写的,希望能够在他们精通Git要义的道路上有所帮助。因此,接下来的章节会假定读者已经了解了Git的基本使用,并且度过了学习Git的新手阶段。

本文的内容可以作为Git版本控制基础知识的简单回顾。本文的重点会放在实际应用方面,通过开发一个简易示例项目,演示和解说基本的版本控制操作,以及两个开发者之间的协作流程。

本文将会介绍以下知识:

  • 搭建Git环境和创建Git版本库(init、clone)。
  • 文件添加、状态检查、创建注释和查看历史记录。
  • 与其他Git版本库交互(pull、push)。
  • 解决合并冲突。
  • 创建分支列表、列表切换和合并。
  • 创建标签。

1.1 版本控制与Git

版本控制系统(有时也称修订控制)是一种用户可以根据时间追溯项目文件(存放于版本库中)修改历史和属性的工具,它还可以帮助团队成员协作开发。当前流行的版本控制系统可以为每个开发人员提供专属的沙箱,防止他们的工作发生冲突,同时采用冲突合并和同步机制,实现以非阻塞的方式进行高效协作。

像Git这类分布式版本控制系统为每个用户提供专属于其自己的项目历史副本、版本库的副本。Git系统如此高效的原因有以下几个:首先,几乎所有操作都是在用户本机上执行,而且非常灵活;其次,你可以使用多种方式建立版本仓库。版本仓库对于开发来说意味着每个开发人员都有整个项目文件的独立工作区(也称工作目录)。Git采用的分支模型支持本地分支,而且分支的发布也非常灵活,用户可以使用分支进行内容切换,还可以在开发过程中将不同工作放置于相互隔离的沙箱中(有可能构建出独立、灵活的主题分支工作流)。

事实上,版本库的整个变更历史都是可以访问的,用户可以撤销或者回退更改过的内容到最后一个工作版本等。当每个修改被提交之后,用户的修改提交记录也被记录下来,因此提交代码修改的用户也就很容易被定位。你还可以比较文件的不同版本,将代码回退到某个用户提交bug报告之前的版本,甚至可以知道哪个版本的变更导致了上述bug。其实,Git主要是通过reflog命令来跟踪分支的变更记录信息并实现回退和覆盖目的的。

Git有一个独特的功能是它支持显式访问暂存区以便创建注释(对项目进行新的修订)。这为用户管理工作区和确定将来的注释信息带来了更多灵活性。

所有这些灵活、强大的特性都是要付出代价的。虽然掌握Git的基本使用非常简单,但是精通Git的使用并不是那么容易。本文将会帮助你在成为Git专家的道路上披荆斩棘,不过在此让我们先来回顾一下Git的基本使用。

1.2 Git简易示例

让我们通过两个开发人员在一个简单项目上使用Git进行协作开发来一步一步地构建一个简单示例。读者可以从http://www.packtpub.com下载相关的项目示例代码。你会发现本文的示例代码文件中包含3个版本库(一个是服务端的,另外两个是开发者的),而且你可以浏览版本库的代码、查询修改历史、执行reflog命令等。

1.2.1 创建版本库

某公司准备研发一款新产品。该产品主要的用途是从特定区间内随机获取若干个整数。

该公司指派了两名开发人员负责这个新项目,他们的名字分别是Alice和Bob。两名远程办公的开发人员经过和公司领导协商之后,决定使用C语言开发一套命令行应用来完成该产品的研发,并且使用Git 2.5.0(http://git-scm.com/)进行程序代码版本控制管理。该产品的用途主要是用来进行过程演示的,而且也非常简单。程序代码的细节并不是重点,我们关注的是如何管理代码变更。

团队规模很小,因此他们决定以图1-1所示的组织结构启动项目。

图1-1 启动项目的组织结构

这个启动配置非常自由,虽然有中心版本库,但是却没有专人负责维护它(项目启动之初,所有开发者的角色都是平等的)。启动项目的组织形式多样,如果你希望深入了解与此有关的知识,可以参考以后文章的内容。

1.2.2 创建Git版本库

Alice在项目启动时请求管理员Carol为她创建一个新的版本库以方便团队协作。

命令行示例遵循的是UNIX系统风格,命令行前面的提示信息由“用户名@主机名/文件目录”组成,这样一眼就可以看出由谁执行该命令,属于哪台计算机以及文件目录是什么。上述风格在UNIX环境中很常见(在Linux系统下也是如此)。可以参考第10章的内容,让Git系统显示特定信息,例如版本库名称、版本库下的子目录名、当前分支,甚至工作区的状态信息。

我认为显示服务端配置的细节对于本文来说有点多余了。因此,为了行文简洁,不相关的信息就省略了。如果希望了解详情,参考后文即可。

你还可以使用工具来管理Git的版本库(例如Gitolite),在服务端创建一个版本库也许看上去会稍有不同。通常情况下是使用git init(不带“--bare”参数)命令创建版本库,然后根据特定的URL地址将其推送到服务端,执行上述操作之后,服务端会自动创建一个公共版本库。或者也可以使用带Web接口工具的网站创建该版本库,例如GitHub、Bitbucket和GitLab(可以托管或内部部署)

1.2.3 克隆版本库并添加注释

Bob知道项目版本库就绪的消息之后,就开始了编写代码的工作。

因为这是他在本项目中首次使用Git,因此,他在自己的版本库根目录下建立了对应的~/.gitconfig文件,该文件主要是用来帮助他标记日志文件中特定的注释信息:

现在他需要获取自己的版本库实例:

本文所有示例使用的都是命令行接口。这些命令也可以使用Git的GUI应用程序或者IDE集成环境完成。Packt出版社发行的The Git: Version Control for Everyone Book详细介绍了GUI界面替代命令行执行任务的具体细节。

Bob注意到Git系统提示说这是一个空的版本库,还没有代码文件,所以他开始编写代码了。他打开了文本编辑器,为本项目创建了第一版代码程序:

一般来说,和大部分原始程序实现类似,该程序还非常简陋。不过这是一个很好的开端。在提交代码之前,Bob希望这个程序可以通过编译并能够运行:

好的!现在把该文件添加到版本库中:

Bob使用“status”命令来确保先前的所有修改都没什么问题:

为了节省示例篇幅,我们截取了git status命令的部分内容。你可以在后续内容中看到执行该命令后的完整内容输出。

Git系统显示了警告信息,因为它不知道该如何处理a.out文件:它既没有在跟踪列表中,也没有在忽略列表中。它是编译过程中生成的可执行体,不应该存放于版本库中。Bob可以暂时不用理会这个提示信息。

现在,向服务端提交(commit)该代码文件:

一般来说,在添加注释信息时,不仅可以使用-m <信息> 命令行选项,还可以让Git打开一个文本编辑器完成相关操作。本示例使用这种格式是为了让示例代码看起来更紧凑。

-a/--all 选项的意思是接受被追踪文件的所有变更,你可以在暂存区创建一个注释来实现操作隔离,不过这是另外一个问题了。详情可以参考第4章内容。

1.2.4 发布修改

在完成项目的初始版本之后,Bob准备发布它们(提交到服务器,供团队其他成员访问)。他将自己的工作成果推送到了服务端:

注意

Git会根据用户的网络速度,显示诸如clone、push和fetch操作的具体进度。为了简单起见,本文示例省略了这些内容,当需要查看代码文件历史和变更记录时才会显示相关信息。

1.2.5 查看历史版本

因为这是Alice第一次在她的个人电脑上使用Git,因此,她必须告诉Git系统如何识别她提交的注释:

现在Alice需要建立专属于她自己的版本库实例:

Alice打算查看一下工作目录:

目录下包含Alice的版本库的拷贝(克隆),并且这些文件是以Git内部格式存在的,同时还包含一些针对版本库的管理信息。你可以在Git帮助手册中的gitrepository- layout(5)章节找到文件格式的详细说明,只需要在命令行中键入git help repository-layout命令即可。

她希望查看日志的细节信息(查看项目历史记录):

修订追踪:

在最底层实现中,Git历史版本识别是通过一个SHA-1哈希码实现的,例如2b953b4e80。Git支持多种形式的版本查询,其中就包括SHA-1码精确匹配(最少提供4个字符)。请参考第2章了解详情。

当Alice决定浏览一遍代码时,她突然发现了一个严重的问题:随机数生成部分一直都没有初始化!她经过一个快速测试发现程序生成的结果都是同一个数。幸运的是,她并不需要修改main()内部的代码,只需要在顶部加入相应的#include引用即可:

改完代码之后,她运行了几次程序,来确认程序真的可以生成随机数。一切似乎都进行得很顺利。她使用git status命令查看了之前的文件变更:

不必感到大惊小怪。Git知道random.c文件被修改了。然后Alice使用git diff命令再次确认对代码的修改:

从现在开始,我们将不会显示未被跟踪的文件信息,除非它和讨论的主题相关。现在假定Alice已经生成了一个忽略配置文件。该配置文件的详情,可以参考第4章。

现在,可以提交变更,然后将它们发布到公共版本库了:

1.2.6 重命名、移动文件

Bob接下来的工作是重构工作区目录。他不希望版本库的顶层目录文件太多,所以他决定将所有源代码文件移动到“src/”子目录下:

现在,他为了确保目录重构之后使用“diff”命令输出结果的差异不至于太大,将Git系统配置为始终执行重命名和拷贝的检测:

Bob觉得是时候为项目添加一个合适的Makefile配置文件,以及一个README帮助文件了:

Bob将“random.c”文件的名字改为“rand.c”:

上述操作当然也需要修改Makefile文件:

然后,他提交了这些修改。

1.2.7 更新版本库(合并)

项目文件重组完成之后,Bob打算将这些变更推送到服务端:

但是Alice同时也在这个项目中工作,而且她已经向服务端推送了自己的代码。Git系统现在不允许Bob推送他对项目代码的变更,因为Alice已经推送了一些内容到master分支上,系统会保护她提交的变更。

为了行文简洁,Git命令行中输出的提示和帮助信息在后续篇章中会略去。

Bob使用“pull”命令将服务端版本库的内容与自己的版本库同步(像命令行提示信息建议的那样):

执行“pull”命令之后,Git系统会将服务端版本库中的变更下载到Bob本机,然后自动将它们和Bob本机版本库的变更合并,最后把合并后的变更提交到本机版本库中。

现在万事俱备了:

合并后的提交也完成了。Git系统可以直接将Alice提交的变更与Bob移动或重命名后的文件合并,是不是很神奇呢?

Bob检查编译(因为自动合并之后并不能绝对保证代码没问题)了一下变更合并后的代码,准备将合并变更后的代码推送到服务端:

1.2.8 创建标签

Alice和Bob认为项目可以进行更大范围的发布了。Bob创建了一个标签(tag),以便日后他们方便地访问/引用发布过的预览版本。他为此使用了一个带注释的标签,当然大家一般采用的替代性方案是使用带数字签名的标签,该标签通常会包含一个PGP数字签名(以后的验证需要用到它):

当然,v0.1版的标签如果只放在Bob本地的版本库中是没有什么意义的。接下来他将刚创建的标签推送到服务端:

Alice为了获得这个标签,更新了她的版本库,然后开始了她的日常工作:

1.2.9 解决合并冲突

Alice认为将生成伪随机数功能修改成一个单独的子程序是个好主意。这样一来,初始化和生成随机数的功能都独立封装起来了,将来需求变更的时候更容易实现一些。她决定给程序添加一个init_rand()函数:

接下来,编译运行一下代码,看看有没有什么问题:

通过编译,程序没什么问题之后就可以提交变更了:

从提示信息可以看到,提交成功了。

同时,Bob在与rand()函数相关的开发文档中发现,它是用来生成简单的伪随机数的标准函数,可能并不能满足实际需要:

他决定在提交代码变更的注释中添加对此问题的备注说明:

他提交代码的变更之后,将它们推送到了服务端:

因此,当Alice准备推送她的变更到服务端时,Git系统拒绝了该操作:

Bob一定是推送了不少变更到服务端。Alice需要再次从服务端的版本库上下载最新版本的项目文件,然后亲自把自己的变更和Bob的变更合并:

该合并操作并没有像上次那样被顺利执行。Git系统无法自动合并Alice和Bob两人提交的变更。显然,文件变更之间有冲突。Alice决定用文本编辑器打开文件“src/rand.c”一探究竟(她也可以使用图形化的合并工具查看代码差异):

Git系统中现在既有Alice提交的代码变更(在<<<<<<<< HEAD和======== 冲突标记之间),也有Bob提交的代码变更(在========和 >>>>>>>>之间)。我们希望的结果是将两人的代码融为一体。Git系统无法自动合并它们,因为这些代码块并不是独立的。Alice的init_rand()函数可以简单地插入Bob添加的代码注释之前。执行上述操作之后,结果如下:

这样冲突应该就可以解决了。Alice重新编译运行了一下程序,然后提交了这一变更:

然后她尝试将该变更推送到服务端版本库:

大功告成!

1.2.10 添加和移除文件

Bob打算给项目添加一个和版权声明有关的COPYRIGHT文件,当然还打算添加一个记录软件新特性的文件(不过还没有创建),所以他使用批处理命令添加了工作区中的所有文件到版本库中:

因为Bob没有配置的忽略模式,因此作为备份文件的“COPYRIGHT~”也被提交到了版本库。接下来我们移除该文件:

检查一下文件状态,然后提交变更:

1.2.11 撤销对单个文件的修改

百无聊赖之际,Bob决定调整一下文件rand.c的代码缩进格式,使之符合统一的命名规范。

他统计了一下该文件源代码的变更记录:

样式调整的变更太多了(对于如此小的文件来说),在合并时可能会出问题。Bob冷静了一下,然后撤销了对文件rand.c的样式调整:

如果你不记得如何回退一个特定类型的变更或者更新某个已提交的变更(使用不带“-a”参数的命令“git commit”),执行“git status”命令(不带“-s”参数)后的输出结果会包含如下所示的帮助信息:

1.2.12 创建新分支

Alice注意到代码中取模运算返回给定区间内随机数的分布并不是均匀的,因为大部分情况下返回的都是较小的数。她打算修复这个问题。为了将相关的开发工作和代码中的其他变更隔离,她决定在自己的版本库中创建一个新分支(分支的具体使用可以参考第6章),然后切换到该分支:

除了使用“git checkout –b better-random”命令创建一个新分支,然后使用命令切换到该分支之外,她还可以首先使用“git branch better-random”命令创建一个新分支,然后使用“git checkout better-random”命令切换到该分支。

她决定使用RAND_MAX常量控制

rand()

函数生成随机数的范围。相关的代码修改如下:

她提交了上述代码变更,然后将它们推送到了服务端,她知道上述推送操作可以顺利执行,因为这些操作都是在她的私有分支上进行的:

通过上述信息可以知道,Git系统希望Alice为她新创建的分支(它采用的推送策略是simple模式)在远程版本库中添加对应的上游分支,这样可以让分支推送到远程分支的目标更明确。

如果她希望更直观地管理她自己的分支结构并且只对自己可见,那么她需要配置好与服务端的相关映射,或者使用诸如Gitolite之类Git版本库管理软件来管理自己的分支。

1.2.13 合并分支(无冲突)

与此同时,在默认的主分支下,Bob打算推送自己给项目添加COPYRIGHT文件的变更:

出现上述错误提示是因为Alice当时正在忙着将初始化生成随机数的部分代码封装为一个子程序(解决合并冲突),她首先向服务端版本库推送了自己的变更:

Git系统可以轻松地将Alice推送的变更合并,但是现在出现了一个新分支。接下来我们来看看具体细节。为了节省篇幅,下文只显示和该新分支“better- random”相关的内容(双点符号的详细用法可以参考第2章):

有趣的是,Bob希望从服务端获取Alice创建的新分支然后合并到自己的版本库的默认分支下(该新分支在远程版本库上已经存在):

1.2.14 撤销未发布的合并

Bob意识到何时将该特性添加到主分支中应该由Alice来做决定。他打算撤销上述合并操作。因为这些变更还没有发布,因此只需要简单地将自己的本地主分支回退到上一次提交的变更状态即可:

本示例演示了使用日志引用(reflog)机制实现变更回退操作。另外一种解决方案是使用“HEAD^”代替“@{1}”,这样也可以实现同样的效果。

1.3 小结

本文的主要内容是演示了一个小型开发团队在一个简单项目中协作开发的大致流程。

回顾了如何将Git和实际的研发工作集成以提高工作效率,以及创建新的版本库或者克隆一个已有的版本库;还学习了提交项目变更之前对文件的添加、编辑、移动和重命名等操作,以及如何查看项目状态和已提交的变更历史,创建预览版项目标签。

回顾了如何使用Git在同一项目中的团队协作,如何发布自己的变更,如何获取团队其他成员的成果。因为使用Git可以帮助团队成员同步开发,有时在多个团队成员之间,Git需要用户手动解决合并冲突。

回顾了如何为软件预览版程序创建标签,以及为某一个特定功能创建独立分支。Git需要用户显式推送标签和分支,但是获取它们是自动的。我们还学习了如何合并分支。



本文摘自《Git高手之路》

《Git高手之路》

Jakub Nar?bski 著

点击封面购买纸书

本书面向所有的Git用户,全面细致地向读者介绍有关Git的各项实用技巧,充分发掘它的潜力,更好地实现项目版本管理。学习本书,可以帮助读者更好地运用Git,提升软件开发效率。



小福利

关注【异步社区】服务号,转发本文至朋友圈或 50 人以上微信群,截图发送至异步社区服务号后台,并在文章底下留言你的开发经验,或者试读本书感受,我们将选出3名读者赠送《Git高手之路》1本,赶快积极参与吧!
活动截止时间:2018年4月16日

在“异步社区”后台回复“关注”,即可免费获得2000门在线视频课程;推荐朋友关注根据提示获取赠书链接,免费得异步图书一本。赶紧来参加哦!

扫一扫上方二维码,回复“关注”参与活动!

阅读原文,购买《Git高手之路》

阅读原文

原文地址:http://blog.51cto.com/13127751/2097145

时间: 2024-07-30 16:37:24

如何快速入门Git应用?(文末福利)的相关文章

快速入门git第七步

2.7 Git 基础 - 技巧和窍门技巧和窍门在结束本章之前,我还想和大家分享一些 Git 使用的技巧和窍门.很多使用 Git 的开发者可能根本就没用过这些技巧,我们也不是说在读过本书后非得用这些技巧不可,但至少应该有所了解吧.说实话,有了这些小窍门,我们的工作可以变得更简单,更轻松,更高效. 自动补全如果你用的是 Bash shell,可以试试看 Git 提供的自动补全脚本.下载 Git 的源代码,进入 contrib/completion 目录,会看到一个 git-completion.ba

快速入门git第一步

版本控制的知识. 一.版本控制VC:是一种记录了任何文本内容的改变,方便以后查阅版本改变 二.版本控制系统VCS: 简单来说的好处就是便于回到之前的某个版本,有一下的好处:      1.文件可回到某个状态,甚至是系统回到了某个状态点      2.可以即使的查看文档改动的内容      3.可以查看谁提交了代码,修改的内容是什么,发起修改的是谁,方便检查bug是谁导致的,方便管理三.集中化的版本控制系统CVCS工作原理: 所有的版本控制放在一台服务器上(体现了集中),客户端通过拉取代码或提交代

使用Spring Boot构建微服务(文末福利)

本文主要内容 学习微服务的关键特征 了解微服务是如何适应云架构的 将业务领域分解成一组微服务 使用Spring Boot实现简单的微服务 掌握基于微服务架构构建应用程序的视角 学习什么时候不应该使用微服务 软件开发的历史充斥着大型开发项目崩溃的故事,这些项目可能投资了数百万美元.集中了行业里众多的顶尖人才.消耗了开发人员成千上万的工时,但从未给客户交付任何有价值的东西,最终由于其复杂性和负担而轰然倒塌. 这些庞大的项目倾向于遵循大型传统的瀑布开发方法,坚持在项目开始时界定应用的所有需求和设计.这

快速入门git第六步

远程仓库的使用远程仓库是依托在网上的管理的项目,有些只能读,或可以写git remote 命令列出了该项目所有的远程仓库的简短名(它对应的是仓库的地址即url,如origin实际上是一个url),克隆或提交项目需要该名,默认是origin的远程库git remote -v 列出了简短名和url添加一个远程仓库: git remote add 简短名 url 如果是ssh协议则url 是用户名@ip:文件路径, 如果是github拉取项目,则是git://url.git远程仓库建好后,git pu

快速入门git第四步

一.获得git仓库有两个来源:1.在现有的目录下,通过git add 导入文件创建新的git仓库 2.从以后的git仓库下克隆下代码 1.在工作目录下新建git仓库,使项目进行了git的管理,只需要进行下列的命令: cd 文件名(进入目录)或者直接建立一个文件夹(mkdir zhen/cd zhen/) git init git init 做了写什么? 该命令的叫做初始化,初始化目录里面的文件和结构,在该目录下胡出现一个.git的文件,该文件含有git所需要的 资源和数据 2.克隆代码: git

快速入门git第五步

在初始化仓库的时候,做好用git --bare init 而不要用git init ,如果使用了git init初始化,则远程仓库的目录下,也包含work tree,当本地仓库向远程仓库push时, 如果远程仓库正在push的分支上(如果当时不在push的分支,就没有问题), 那么push后的结果不会反应在work tree上, 也即在远程仓库的目录下对应的文件还是之前的内容,必须得使用git reset --hard才能看到push后的内容.查看历史记录: git log git log -p

快速入门git第三步

安装:一.在linux ubuntu 上安装git sudo apt-get install git配置:二.初次运行git的配置,为什么是初次,因为更新或升级都会沿用老的git的配置, 可以用相同的命令进行了配置的修改, git 提供了一个工具git config ,专门用来配置或读取相应的环境变量,不同的环境变量导致了git在各个环节的具体工作方式和行为,环境变量存放在三个地方:/ect/config: 系统中对所有的用户都普遍使用的配置-/config: 只是适用与当前用户的配置.git/

快速入门git第二步

git的思想和工作原理: 一.git对改变的文件进行了一次快照,然后保存在一个微型的文件系统里,每次更新代码时,git会遍历所有的文件并进行了改变文件的快照,然后用一个所以指向它,如果没有文件      进行了改变,git只对上一次快照链接进行了浏览 二.git的很多工作都在本地仓库(本地数据库)进行的,因为克隆下来的 项目里已经含有了所有的当前项目的历史记录,可以实现了对以前版本的查看,无需网络,所以可实现在随      随地的进行修改代码,查看修改那些地方,和历史记录 三.数据保存到git时

告别“臃肿”,选择微服务(文末福利)

点击标题下「异步社区」可快速关注 参与文末话题讨论,每周赠送异步图书 --异步小编 一直以来,系统的架构设计是IT领域经久不衰的话题,也是构建每一个系统最核心且重要的部分之一.它决定了系统能否满足业务.技术.组织.灵活.可扩展性等多种要求,同时肩负起了解放程序员生产力的作用. 2016年底,由于业务的不断发展,我所在公司维护的项目也越来越"臃肿".随着无数个版本的迭代,以及开发人员的不断增加,开发效率越来越低,每次投产的人力成本和时间成本都逐渐增加,我们一直在思索如何能破局.评估了各种

异步5月新书,大咖云集本本经典(文末福利)

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书. --异步小编 5月小长假回来,小编带来了18本异步新书,这些新书涵盖热点领域Python.深度学习.CPU设计.微服务.少儿编程等领域.可以说本本重点. 有一种语言叫Python <"笨办法学"Python3>基于Python3.6,支持手机扫码看视频.入门级 <Python编程从入门到精通>基于Python3,33小时视频讲解.900多案例分析.入门级