如何使用git git生成密钥patch

GNU Linux中使用diff生成补丁与用patch打补丁_Linux教程_Linux公社-Linux系统门户网站
你好,游客
GNU Linux中使用diff生成补丁与用patch打补丁
来源:Linux社区&
作者:Linux
在GNU Linux系统编程中,经常会用到diff与patch生成补丁与打补丁,原来对这方面不了解,也就觉得难,做过之后发现并没有什么。
1、使用diff生成补丁;
diff是Linux下的文件比较命令,参数这里就不说了,直接man一下就行了,不仅可以比较文件,也可以比较两个目录,并且可以将不同之处生成补丁文件,其实就是一种打补丁的命令。使用方法如下:
diff -rNu a b & diff.patch
其中,a是旧的目录或文件,b为最近修改后的目录或文件,生成的补丁文件为patch。
2、使用patch打补丁;
patch命令的参数详见man手册,使用patch给另外一个a目录打补丁时如下:
patch -p0 & diff.patch
本文永久更新链接地址:
相关资讯 & & &
& (02月18日)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款1st Edition
5.3 分布式 Git - 项目的管理
项目的管理
既然是相互协作,在贡献代码的同时,也免不了要维护管理自己的项目。像是怎么处理别人用 format-patch 生成的补丁,或是集成远端仓库上某个分支上的变化等等。但无论是管理代码仓库,还是帮忙审核收到的补丁,都需要同贡献者约定某种长期可持续的工作方式。
如果想要集成新的代码进来,最好局限在特性分支上做。临时的特性分支可以让你随意尝试,进退自如。比如碰上无法正常工作的补丁,可以先搁在那边,直到有时间仔细核查修复为止。创建的分支可以用相关的主题关键字命名,比如 ruby_client 或者其它类似的描述性词语,以帮助将来回忆。Git 项目本身还时常把分支名称分置于不同命名空间下,比如 sc/ruby_client 就说明这是 sc 这个人贡献的。
现在从当前主干分支为基础,新建临时分支:
$ git branch sc/ruby_client master
另外,如果你希望立即转到分支上去工作,可以用 checkout -b:
$ git checkout -b sc/ruby_client master
好了,现在已经准备妥当,可以试着将别人贡献的代码合并进来了。之后评估一下有没有问题,最后再决定是不是真的要并入主干。
如果收到一个通过电邮发来的补丁,你应该先把它应用到特性分支上进行评估。有两种应用补丁的方法:git apply 或者 git am。
使用 apply 命令应用补丁
如果收到的补丁文件是用 git diff 或由其它 Unix 的 diff 命令生成,就该用 git apply 命令来应用补丁。假设补丁文件存在 /tmp/patch-ruby-client.patch,可以这样运行:
$ git apply /tmp/patch-ruby-client.patch
这会修改当前工作目录下的文件,效果基本与运行 patch -p1 打补丁一样,但它更为严格,且不会出现混乱。如果是 git diff 格式描述的补丁,此命令还会相应地添加,删除,重命名文件。当然,普通的 patch 命令是不会这么做的。另外请注意,git apply 是一个事务性操作的命令,也就是说,要么所有补丁都打上去,要么全部放弃。所以不会出现 patch 命令那样,一部分文件打上了补丁而另一部分却没有,这样一种不上不下的修订状态。所以总的来说,git apply 要比 patch 严谨许多。因为仅仅是更新当前的文件,所以此命令不会自动生成提交对象,你得手工缓存相应文件的更新状态并执行提交命令。
在实际打补丁之前,可以先用 git apply --check 查看补丁是否能够干净顺利地应用到当前分支中:
$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
如果没有任何输出,表示我们可以顺利采纳该补丁。如果有问题,除了报告错误信息之外,该命令还会返回一个非零的状态,所以在 shell 脚本里可用于检测状态。
使用 am 命令应用补丁
如果贡献者也用 Git,且擅于制作 format-patch 补丁,那你的合并工作将会非常轻松。因为这些补丁中除了文件内容差异外,还包含了作者信息和提交消息。所以请鼓励贡献者用 format-patch 生成补丁。对于传统的 diff 命令生成的补丁,则只能用 git apply 处理。
对于 format-patch 制作的新式补丁,应当使用 git am 命令。从技术上来说,git am
能够读取 mbox 格式的文件。这是种简单的纯文本文件,可以包含多封电邮,格式上用 From 加空格以及随便什么辅助信息所组成的行作为分隔行,以区分每封邮件,就像这样:
From 092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith &&
Date: Sun, 6 Apr :23 -0700
Subject: [PATCH 1/2] add limit to log function
Limit log functionality to the first 20
这是 format-patch 命令输出的开头几行,也是一个有效的 mbox 文件格式。如果有人用 git send-email 给你发了一个补丁,你可以将此邮件下载到本地,然后运行 git am 命令来应用这个补丁。如果你的邮件客户端能将多封电邮导出为 mbox 格式的文件,就可以用 git am 一次性应用所有导出的补丁。
如果贡献者将 format-patch 生成的补丁文件上传到类似 Request Ticket 一样的任务处理系统,那么可以先下载到本地,继而使用 git am 应用该补丁:
$ git am 0001-limit-log-function.patch
Applying: add limit to log function
你会看到它被干净地应用到本地分支,并自动创建了新的提交对象。作者信息取自邮件头 From 和 Date,提交消息则取自 Subject 以及正文中补丁之前的内容。来看具体实例,采纳之前展示的那个 mbox 电邮补丁后,最新的提交对象为:
$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a
Jessica Smith &&
AuthorDate: Sun Apr 6 10:17:23
Scott Chacon &&
CommitDate: Thu Apr 9 09:19:06
add limit to log function
Limit log functionality to the first 20
Commit 部分显示的是采纳补丁的人,以及采纳的时间。而 Author 部分则显示的是原作者,以及创建补丁的时间。
有时,我们也会遇到打不上补丁的情况。这多半是因为主干分支和补丁的基础分支相差太远,但也可能是因为某些依赖补丁还未应用。这种情况下,git am 会报错并询问该怎么做:
$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run &git am --resolved&.
If you would prefer to skip this patch, instead run &git am --skip&.
To restore the original branch and stop patching run &git am --abort&.
Git 会在有冲突的文件里加入冲突解决标记,这同合并或衍合操作一样。解决的办法也一样,先编辑文件消除冲突,然后暂存文件,最后运行 git am --resolved 提交修正结果:
$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: seeing if this helps the gem
如果想让 Git 更智能地处理冲突,可以用 -3 选项进行三方合并。如果当前分支未包含该补丁的基础代码或其祖先,那么三方合并就会失败,所以该选项默认为关闭状态。一般来说,如果该补丁是基于某个公开的提交制作而成的话,你总是可以通过同步来获取这个共同祖先,所以用三方合并选项可以解决很多麻烦:
$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
像上面的例子,对于打过的补丁我又再打一遍,自然会产生冲突,但因为加上了 -3 选项,所以它很聪明地告诉我,无需更新,原有的补丁已经应用。
对于一次应用多个补丁时所用的 mbox 格式文件,可以用 am 命令的交互模式选项 -i,这样就会在打每个补丁前停住,询问该如何操作:
$ git am -3 -i mbox
Commit Body is:
--------------------------
seeing if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
在多个补丁要打的情况下,这是个非常好的办法,一方面可以预览下补丁内容,同时也可以有选择性的接纳或跳过某些补丁。
打完所有补丁后,如果测试下来新特性可以正常工作,那就可以安心地将当前特性分支合并到长期分支中去了。
如果贡献者有自己的 Git 仓库,并将修改推送到此仓库中,那么当你拿到仓库的访问地址和对应分支的名称后,就可以加为远程分支,然后在本地进行合并。
比如,Jessica 发来一封邮件,说在她代码库中的 ruby-client 分支上已经实现了某个非常棒的新功能,希望我们能帮忙测试一下。我们可以先把她的仓库加为远程仓库,然后抓取数据,完了再将她所说的分支检出到本地来测试:
$ git remote add jessica git:///jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client
若是不久她又发来邮件,说还有个很棒的功能实现在另一分支上,那我们只需重新抓取下最新数据,然后检出那个分支到本地就可以了,无需重复设置远程仓库。
这种做法便于同别人保持长期的合作关系。但前提是要求贡献者有自己的服务器,而我们也需要为每个人建一个远程分支。有些贡献者提交代码补丁并不是很频繁,所以通过邮件接收补丁效率会更高。同时我们自己也不会希望建上百来个分支,却只从每个分支取一两个补丁。但若是用脚本程序来管理,或直接使用代码仓库托管服务,就可以简化此过程。当然,选择何种方式取决于你和贡献者的喜好。
使用远程分支的另外一个好处是能够得到提交历史。不管代码合并是不是会有问题,至少我们知道该分支的历史分叉点,所以默认会从共同祖先开始自动进行三方合并,无需 -3 选项,也不用像打补丁那样祈祷存在共同的基准点。
如果只是临时合作,只需用 git pull 命令抓取远程仓库上的数据,合并到本地临时分支就可以了。一次性的抓取动作自然不会把该仓库地址加为远程仓库。
$ git pull git:///onetimeguy/project.git
From git:///onetimeguy/project
-> FETCH_HEAD
Merge made by recursive.
现在特性分支上已合并好了贡献者的代码,是时候决断取舍了。本节将回顾一些之前学过的命令,以看清将要合并到主干的是哪些代码,从而理解它们到底做了些什么,是否真的要并入。
一般我们会先看下,特性分支上都有哪些新增的提交。比如在 contrib 特性分支上打了两个补丁,仅查看这两个补丁的提交信息,可以用 --not 选项指定要屏蔽的分支 master,这样就会剔除重复的提交历史:
$ git log contrib --not master
commit 5b589efc4dd484f118
Author: Scott Chacon &&
Fri Oct 24 09:53:59
seeing if this helps the gem
commit d04bea79d0dba5f16a0
Author: Scott Chacon &&
Mon Oct 22 19:38:36
updated the gemspec to hopefully work better
还可以查看每次提交的具体修改。请牢记,在 git log 后加 -p 选项将展示每次提交的内容差异。
如果想看当前分支同其他分支合并时的完整内容差异,有个小窍门:
$ git diff master
虽然能得到差异内容,但请记住,结果有可能和我们的预期不同。一旦主干 master 在特性分支创建之后有所修改,那么通过 diff 命令来比较的,是最新主干上的提交快照。显然,这不是我们所要的。比方在 master 分支中某个文件里添了一行,然后运行上面的命令,简单的比较最新快照所得到的结论只能是,特性分支中删除了这一行。
这个很好理解:如果 master 是特性分支的直接祖先,不会产生任何问题;如果它们的提交历史在不同的分叉上,那么产生的内容差异,看起来就像是增加了特性分支上的新代码,同时删除了 master 分支上的新代码。
实际上我们真正想要看的,是新加入到特性分支的代码,也就是合并时会并入主干的代码。所以,准确地讲,我们应该比较特性分支和它同 master 分支的共同祖先之间的差异。
我们可以手工定位它们的共同祖先,然后与之比较:
$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db
但这么做很麻烦,所以 Git 提供了便捷的 ... 语法。对于 diff 命令,可以把 ... 加在原始分支(拥有共同祖先)和当前分支之间:
$ git diff master...contrib
现在看到的,就是实际将要引入的新代码。这是一个非常有用的命令,应该牢记。
一旦特性分支准备停当,接下来的问题就是如何集成到更靠近主线的分支中。此外还要考虑维护项目的总体步骤是什么。虽然有很多选择,不过我们这里只介绍其中一部分。
一般最简单的情形,是在 master 分支中维护稳定代码,然后在特性分支上开发新功能,或是审核测试别人贡献的代码,接着将它并入主干,最后删除这个特性分支,如此反复。来看示例,假设当前代码库中有两个分支,分别为 ruby_client 和 php_client,如图 5-19 所示。然后先把 ruby_client 合并进主干,再合并 php_client,最后的提交历史如图 5-20 所示。
图 5-19. 多个特性分支
图 5-20. 合并特性分支之后
这是最简单的流程,所以在处理大一些的项目时可能会有问题。
对于大型项目,至少需要维护两个长期分支 master 和 develop。新代码(图 5-21 中的 ruby_client)将首先并入 develop 分支(图 5-22 中的 C8),经过一个阶段,确认 develop 中的代码已稳定到可发行时,再将 master 分支快进到稳定点(图 5-23 中的 C8)。而平时这两个分支都会被推送到公开的代码库。
图 5-21. 特性分支合并前
图 5-22. 特性分支合并后
图 5-23. 特性分支发布后
这样,在人们克隆仓库时就有两种选择:既可检出最新稳定版本,确保正常使用;也能检出开发版本,试用最前沿的新特性。
你也可以扩展这个概念,先将所有新代码合并到临时特性分支,等到该分支稳定下来并通过测试后,再并入 develop 分支。然后,让时间检验一切,如果这些代码确实可以正常工作相当长一段时间,那就有理由相信它已经足够稳定,可以放心并入主干分支发布。
大项目的合并流程
Git 项目本身有四个长期分支:用于发布的 master 分支、用于合并基本稳定特性的 next 分支、用于合并仍需改进特性的 pu 分支(pu 是 proposed updates 的缩写),以及用于除错维护的 maint 分支(maint 取自 maintenance)。维护者可以按照之前介绍的方法,将贡献者的代码引入为不同的特性分支(如图 5-24 所示),然后测试评估,看哪些特性能稳定工作,哪些还需改进。稳定的特性可以并入 next 分支,然后再推送到公共仓库,以供其他人试用。
图 5-24. 管理复杂的并行贡献
仍需改进的特性可以先并入 pu 分支。直到它们完全稳定后再并入 master。同时一并检查下 next 分支,将足够稳定的特性也并入 master。所以一般来说,master 始终是在快进,next 偶尔做下衍合,而 pu 则是频繁衍合,如图 5-25 所示:
图 5-25. 将特性并入长期分支
并入 master 后的特性分支,已经无需保留分支索引,放心删除好了。Git 项目还有一个 maint 分支,它是以最近一次发行版为基础分化而来的,用于维护除错补丁。所以克隆 Git 项目仓库后会得到这四个分支,通过检出不同分支可以了解各自进展,或是试用前沿特性,或是贡献代码。而维护者则通过管理这些分支,逐步有序地并入第三方贡献。
衍合与挑拣(cherry-pick)的流程
一些维护者更喜欢衍合或者挑拣贡献者的代码,而不是简单的合并,因为这样能够保持线性的提交历史。如果你完成了一个特性的开发,并决定将它引入到主干代码中,你可以转到那个特性分支然后执行衍合命令,好在你的主干分支上(也可能是develop分支之类的)重新提交这些修改。如果这些代码工作得很好,你就可以快进master分支,得到一个线性的提交历史。
另一个引入代码的方法是挑拣。挑拣类似于针对某次特定提交的衍合。它首先提取某次提交的补丁,然后试着应用在当前分支上。如果某个特性分支上有多个commits,但你只想引入其中之一就可以使用这种方法。也可能仅仅是因为你喜欢用挑拣,讨厌衍合。假设你有一个类似图 5-26 的工程。
图 5-26. 挑拣(cherry-pick)之前的历史
如果你希望拉取e43a6到你的主干分支,可以这样:
$ git cherry-pick e43a6fd3ead79fb568ed180e5fcdf
Finished one cherry-pick.
[master]: created a0a41a9: &More friendly message when locking the index fails.&
3 files changed, 17 insertions(+), 3 deletions(-)
这将会引入e43a6的代码,但是会得到不同的SHA-1值,因为应用日期不同。现在你的历史看起来像图 5-27.
图 5-27. 挑拣(cherry-pick)之后的历史
现在,你可以删除这个特性分支并丢弃你不想引入的那些commit。
你可以删除上次发布的版本并重新打标签,也可以像第二章所说的那样建立一个新的标签。如果你决定以维护者的身份给发行版签名,应该这样做:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: &Scott Chacon &&&
1024-bit DSA key, ID F721C45A, created
完成签名之后,如何分发PGP公钥(public key)是个问题。(译者注:分发公钥是为了验证标签)。还好,Git的设计者想到了解决办法:可以把key(即公钥)作为blob变量写入Git库,然后把它的内容直接写在标签里。gpg --list-keys命令可以显示出你所拥有的key:
$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
1024D/F721C45A
[expires: ]
Scott Chacon &&
[expires: ]
然后,导出key的内容并经由管道符传递给git hash-object,之后钥匙会以blob类型写入Git中,最后返回这个blob量的SHA-1值:
$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797dec71ac3f9ba29fe5775b92
现在你的Git已经包含了这个key的内容了,可以通过不同的SHA-1值指定不同的key来创建标签。
$ git tag -a maintainer-pgp-pub 659ef797dec71ac3f9ba29fe5775b92
在运行git push --tags命令之后,maintainer-pgp-pub标签就会公布给所有人。如果有人想要校验标签,他可以使用如下命令导入你的key:
$ git show maintainer-pgp-pub | gpg --import
人们可以用这个key校验你签名的所有标签。另外,你也可以在标签信息里写入一个操作向导,用户只需要运行git show &tag&查看标签信息,然后按照你的向导就能完成校验。
因为Git不会为每次提交自动附加类似'v123'的递增序列,所以如果你想要得到一个便于理解的提交号可以运行git describe命令。Git将会返回一个字符串,由三部分组成:最近一次标定的版本号,加上自那次标定之后的提交次数,再加上一段所描述的提交的SHA-1值:
$ git describe master
v1.6.2-rc1-20-g8c5b85c
这个字符串可以作为快照的名字,方便人们理解。如果你的Git是你自己下载源码然后编译安装的,你会发现git --version命令的输出和这个字符串差不多。如果在一个刚刚打完标签的提交上运行describe命令,只会得到这次标定的版本号,而没有后面两项信息。
git describe命令只适用于有标注的标签(通过-a或者-s选项创建的标签),所以发行版的标签都应该是带有标注的,以保证git describe能够正确的执行。你也可以把这个字符串作为checkout或者show命令的目标,因为他们最终都依赖于一个简短的SHA-1值,当然如果这个SHA-1值失效他们也跟着失效。最近Linux内核为了保证SHA-1值的唯一性,将位数由8位扩展到10位,这就导致扩展之前的git describe输出完全失效了。
现在可以发布一个新的版本了。首先要将代码的压缩包归档,方便那些可怜的还没有使用Git的人们。可以使用git archive:
$ git archive master --prefix='project/' | gzip & `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz
这个压缩包解压出来的是一个文件夹,里面是你项目的最新代码快照。你也可以用类似的方法建立一个zip压缩包,在git archive加上--format=zip选项:
$ git archive master --prefix='project/' --format=zip & `git describe master`.zip
现在你有了一个tar.gz压缩包和一个zip压缩包,可以把他们上传到你网站上或者用e-mail发给别人。
是时候通知邮件列表里的朋友们来检验你的成果了。使用git shortlog命令可以方便快捷的制作一份修改日志(changelog),告诉大家上次发布之后又增加了哪些特性和修复了哪些bug。实际上这个命令能够统计给定范围内的所有提交;假如你上一次发布的版本是v1.0.1,下面的命令将给出自从上次发布之后的所有提交的简介:
$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (8):
Add support for annotated tags to Grit::Tag
Add packed-refs annotated tag support.
Add Grit::Commit#to_patch
Update version and History.txt
Remove stray `puts`
Make ls_tree ignore nils
Tom Preston-Werner (4):
fix dates in history
dynamic version method
Version bump to 1.0.2
Regenerated gemspec for version 1.0.2
这就是自从v1.0.1版本以来的所有提交的简介,内容按照作者分组,以便你能快速的发e-mail给他们。
Patches, suggestions and comments are welcome.
Git is a member of保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
单击提交则表示您同意developerWorks
的条款和条件。 .
所有提交的信息确保安全。
developerWorks 社区:
我的概要信息
选择语言:
Git 是 Linux Torvalds 为了帮助管理 Linux® 内核开发而开发的一个开放源码的版本控制软件。我们可以自己下载这个软件用于对内核的 hack 分析,或者用来管理自己的软件开发项目。本文将向您展示如何使用 Git 工具开始分析 Linux 。
(), 软件工程师, IBM
Eli Dow 是位于纽约 Poughkeepsie 的 IBM Linux Test and Integration Center 的软件工程师。他取得了 Clarkson 大学计算机科学与心理学的学士学位和计算机科学硕士学位。他的兴趣包括 GNOME 桌面、人机交互和 Linux 系统编程。他是 IBM 红皮书 Linux for IBM System z9 and IBM zSeries 的作者之一。
在现代软件开发项目中,要成为一个有效的软件开发人员,我们必须能够与其他项目贡献者并行进行开发。源代码管理(SCM)系统不是什么新思想。为了编写一些能够更快速、简单地开发以后软件项目的软件,已经进行了很多尝试。最新的源代码解决方案都包含了版本控制系统,它可以对源代码的修改进行回滚,从而将有害的代码剔除出项目之外,或者简单地跟踪哪些人修改了代码的哪些行的内容。版本控制系统试图解决开发人员在试图同时对某个文件进行修改时所出现的冲突问题,可以防止用户覆盖其他人所作的修改。源代码管理使用的很多流行解决方案都试图解决以前 SCM 解决方案中的失效问题。集中化的版本控制系统通常采用两种方式:有些提供了文件锁来防止多个用户的并行访问。这些系统对文件进行加锁,这样在某个时间只有一个开发人员对中心仓库具有写入权限。另外一些工具,例如 CVS,允许多个开发人员同时对相同的文件进行编辑,并提供了一些机制稍后合并这些修改。流行的版本控制系统包括:CVSSubversionArchBazaarBitKeeper什么是 Git?非常简单地说,Git 是 Linus Torvalds 最近实现的源代码管理软件。正如所提供的文档中说的一样,“Git 是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。”Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper,后者之前一直是 Linux 内核开发人员在全球使用的主要源代码工具。开放源码社区中的有些人觉得 BitKeeper 的许可证并不适合开放源码社区的工作,因此 Torvalds 决定着手研究许可证更为灵活的版本控制系统。尽管最初 Git 的开发是为了辅助 Linux 内核开发的过程,但是我们已经发现在很多其他自由软件项目中也使用了 Git。例如,X.org 最近就迁移到 Git 上来了,很多 Freedesktop.org 的项目也迁移到了 Git 上。
Git 目前主要由寻找 CVS 或专有代码管理解决方案替代物的软件开发人员所使用。Git 与 CVS 有很多区别:分支更快、更容易。支持离线工作;本地提交可以稍后提交到服务器上。Git 提交都是原子的,且是整个项目范围的,而不像 CVS 中一样是对每个文件的。Git 中的每个工作树都包含一个具有完整项目历史的仓库。没有哪一个 Git 仓库会天生比其他仓库更重要。安装要安装当前版本的 Git,我们可以使用供应商在 Linux 发行版中提供的包,或者从最新的稳定快照开始手工进行编译。我建议下载包含最新 Git 源代码稳定快照的 tarball;截止到撰写本文时这个版本是 v1.4.0。我们可以在下面的
一节中找到链接。有了这个 tarball 之后,请确保初始安装所依赖的包都已经安装了。系统中必须包含以下包,以及相应的开发头文件:zliblibcurllibcrypto(OpenSSL)rsync(2.6.0 或更高版本)这些条件满足之后,我们就可以开始编译初始的 Git 安装系统了。这个过程对于大部分一直使用 Linux 的开发人员来说应该非常熟悉了。首先使用对应下载的包格式的命令将包展开:$ tar -jxvf git-1.4.0.tar.bz2或$ tar -zxvf git-1.4.0.tar.gz然后切换到适当的目录中,并执行 make 命令。(注意目录名取决于我们下载的快照的日期。)$ cd git-1.4.0/
$ make prefix=/usr/local install
$ sudo make prefix=/usr/local install您会被提示输入 sudo 密码才能继续安装。现在就已经准备好使用 Git 工具了。获得最新的内核源代码树在使用 Git 管理源代码仓库时,我们可以使用两种方法开始我们的工作。我们可以使用现有代码的一个本地目录,然后从中生成一个仓库;也可以映射其他人发布的仓库。对于本文的目的来说,我们将获得 Torvalds 发布的 Git 仓库的一个镜像。下面的命令将创建一个名为 linux-2.6 的 Git 仓库。这个目录包含了一个隐藏目录 .git/ 。$ git-clone \
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git \
linux-2.6这个步骤会执行很长时间,因为 Git 正在将内核源代码(这有数百兆大)从 kernel.org 传输到本地机器上。输出结果可能有些晦涩难懂,但是如果您有一个快速的 Internet 链接,卷屏的速度应该相当快。输出结果应该类似于图 1 所示。图 1. 在下载内核源代码树过程中产生的输出现在切换到包含新下载的内核的目录中:$ cd linux-2.6现在,我们应该在本地机器上有一个可以工作的 Linux 2.6 仓库了!此时我们就可以对这个仓库进行一些基本的操作了。更新本地 Git 仓库在使用 Git 时,我们通常可以假设自己的仓库可能比 kernel.org 的仓库有些滞后。因此我们通常都是首先将自己的仓库更新成最新的上游内核树。这个过程有时称为快速合并(fast-forward merge)。严格来说,我们现在并不需要执行这个过程,因为我们刚刚安装了自己的仓库,它应该还没有过期。但是检查一下毕竟没有坏处:$ cd linux-2.6
$ git-pull git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
...如果成功,我们就应该会看到类似于下面的输出结果:receiving file list ... done
sent 130 bytes
received 21677 bytes
14538.00 bytes/sec
total size is
speedup is 5863.52
Already up-to-date.
$&如果我们的仓库不是最新的,就会看到有些内容通过网络传输到本地机器上了。从仓库中导出文件我们需要将文件从 Git 仓库(隐藏目录中的那些文件)中导出到工作目录中才能开始自己的 hack 过程。下面的命令会在当前目录中写入没有隐藏的目录,其中包含了 Linux 的源代码:$ git-checkout如果您希望覆盖本地修改,可以使用 -f 选项导出文件,这样就可以将您带回到一个干净的状态:$ git-checkout -f现在在当前工作目录中,我们应该就可以看到熟悉的 Linux 源代码目录结构了,然后我们可以对这些源代码任意进行修改。修改现有文件我们现在可以修改所选择的任何文件。举一个简单的例子来说,我们将修改 docs 目录中的一些内容:添加一条以后可以很容易识别的信息。为了让我的例子更容易试验,我没有选择修改源代码;不过只要您希望,欢迎继续重写整个内核的子系统。首先,让我们在编辑器中打开一个文件:$ vi ./Documentation/ManagementStyle显然,我使用的是 vi;不过您当然可以使用自己喜欢的任何编辑器来完成这项工作。在编辑文件时,我在第一段前面添加了一行:“Eli shall be in charge of managing sandwich consumption. See Documentation/Sandwiches for more.”如果您对自己所做的修改非常满意,并且觉得自己已经准备好将其作为仓库的一个永久部分了,就需要使用下面的命令导入您的修改:$ git-commit Documentation/ManagementStyle您会被提示说要求提供一个提交消息,它是一个用户生成的注释,用来帮助其他开发人员(也可能是您自己以后)理解刚才的实现到底进行了哪些修改。在我们的例子中,提交消息是一个描述刚才对文档所做修改的短句。如果您希望检查一下到目前为止工作的状态,可以执行 git-log 来查看本地仓库的历史(它继承了所克隆的仓库的信息)。您的提交消息应该在日志的最上面。添加或删除文件但是请等一下!我们还没有添加 Documentation/Sandwiches 文件呢,因此我们需要将其添加到工作目录中,并告诉 Git 何时这个文件已经准备好了。我使用 echo 命令创建了想要添加的文件,因为这只是一个简单的例子而已。同样,您也可以使用自己喜欢的工具。$ echo "Turkey is superior" & Documentation/Sandwiches现在我们已经添加了一个文件,接下来需要将这个文件添加到 Git 中,从而让 Git 了解这种变化,然后才能提交这个版本。我们可以通过执行下面的命令来完成这些任务:$ git-add Documentation/Sandwiches
$ git-commit Documentation/Sandwiches如果您添加了多个文件,可以在同一行中的 git-add 命令后面列出这些文件,不过您也不必一次将它们全部添加到仓库中去。如果要删除某个文件,并且没有 git-add 之类的特殊命令;您只需要删除这个文件,然后提交就可以了。现在应该查看一下 git-log,从而确保到现在为止所做的事情都是正确的。这一次,我们将使用 -p 选项来以单独的补丁格式查看日志。$git-log -p创建 diff 文件最后,我们希望生成一个包含您修改后的文件和原文件之间区别的文本文件。这个文件通常是使用 diff 工具创建的,因此就称为 diff 文件。diff 可以帮助我们创建补丁文件(patch file),后者是我们向很多开放源码软件项目发送代码提交时通常使用的方法。有关 diff 的更多内容,请参看下面
部分中有关 Kernel.org 的链接。Git 还可以干什么?我们可以使用 Git 来管理本地仓库,而不用镜像其他人的工作。例如,如果我们喜欢使用 Git 来管理自己个人对某个开放源码项目贡献的文件,就可以从项目快照中生成一个 Git 仓库。假设我们已经有了一个名为 release.tar.gz 的标准 release tarball,可以执行下面的命令来创建一个本地的 Git 仓库:$ tar -zxvf release.tar.gz
$ cd release
$ git init-db我们可以看到消息说 Git 是 “默认于本地存储区域的”。这些消息都是正常的,说明我们有一个 Git 仓库。现在我们已经对工作目录进行了初始化,接下来在项目目录中应该会看到一个新目录 .git。为了告诉 Git 我们希望对这个项目中的每个文件都进行跟踪,请执行下面的命令: $ git add .最后,使用下面的命令将所监视的文件提交到仓库中:$ git commit -a同样,系统会提示我们输入提交消息。从现在开始,我们就可以在自己的 Git 仓库中使用 Git 所提供的完整功能了,例如对实验特性进行分支,为了追踪回归测试问题而将代码一分为二,并使用常见的版本历史功能。有关 Git 的分支管理和其他有趣特性的更多信息,请参看 Kernel.org
上给出的 Git 的优秀教程(参见
中的链接)。结束语现在我们已经知道如何使用 Git 来获取 Linux 内核源代码和其他 Git 管理的项目了,接下来可以选择使用 Git 来管理下一个开发项目。 Git 仍然相对较新,仍然处于不断开发中。其他脚本和工具正在实现用来简化 Git 的使用;请参看
中给出的例子。
参考资料 您可以参阅本文在 developerWorks 全球站点上的
Kernel.org 上有很多很好的入门资源:
是一份开始入门的参考资料。
学习更多有关版本控制系统的知识:
“”(developerWorks,2001 年 3 月)“”(developerWorks,2006 年 6 月)“”(developerWorks,2005 年 2 月) 是有关 Linux 在大型机系统上的 IBM 红皮书。
可以找到为 Linux 开发人员准备的更多资源。
随时关注 。
是一个基于 QT 的 Git GUI。
在您的下一个开发项目中采用 ,这可以从 developerWorks 上直接下载。
加入 developerWorks 社区。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Linux, Open sourceArticleID=153361ArticleTitle=使用 Git 管理源代码publish-date=

我要回帖

更多关于 git 打patch 的文章

 

随机推荐