摘要:Git初学教程
参考: GitPro(中文版)–书籍
一、Git常用命令
1.1 获取Git仓库
- git init:创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件都是 Git 仓库的骨干,但这仅仅是一个初始化的操作,你的项目中的文件并没有被追踪。
- git clone:克隆现有的仓库,例如:
git clone https://github.com/libgit2/libgit2 。
1.2 记录每次更新到仓库
- git status:查看哪些文件处于什么状态。
- git status -s/–short:状态简览。由于
git status 命令输出十分详细,但是其用语相对繁琐,故使用该命令可以以简洁的形式查看更改,得到一种格式更为紧凑的输出。 - git add:跟踪新文件,对所指定的文件进行追踪,并处于暂存状态,
git add *.c ,其中*.c 表示某个文件。 - git diff:以文件补丁的格式更加具体地显示那些行发生了改变,比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
- git diff --staged/–cached:比对已暂存文件与最后一次提交的文件差异。
- git commit:提交更新。将暂存区中的内容提交,在此之前应当确认还有什么已修改或新建的文件没有
git add 过,否则提交的时候不会记录这些尚未暂存的变化。 - git commit --amend:这条命令会将最后一次的提交信息载入到编辑器中供你修改。 当保存并关闭编辑器后,编辑器会将更新后的提交信息写入新提交中,它会成为新的最后一次提交。以新的改进后的提交来 替换掉旧有的最后一次提交。
- git commit -m “提交信息”:将提交信息与命令放在同一行。值得注意的是:提交时记录的是放在暂存区域的快照,任何还未暂存文件的仍然保持已修改的状态,可以在下一次提交时纳入版本管理。每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
- git commit -a:自动将所有已经追踪过的文件暂存起来一并提交,直接跳过了
git add 操作。 - git rm:移除文件。要从 Git 中移除某个文件,就必须要从以跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。
- git rm -f:强制删除。
-f 为强制删除选项,如果要删除之前修改过后已经放入到暂存区的文件,则必须加上-f 。这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。 - git mv file_from file_to:移动文件。重命名操作。
1.3 查看提交历史
-
git log:查看提交历史。 -
git log -p/–patch :查看提交历史。它会显示每次提交所引入的差异(按补丁的格式输出)。同样也可以限制显示的日志条目数量,例如:git log -p -2 表示只显示最近的两次提交。 -
git log --stat:查看每次提交的简略信息。当进行代码审查,或者快速浏览某个搭档的提交所带来的变化的时候,这个参数就非常有用了。--stat :选项在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或者被添加了,在每次提交的最后还有个总结。 -
git log --pretty:该选项可以使用不同默认格式的方式展示提交历史。 -
git log --pretty=format:"%h %s" --graph:--graph 选项表示在日志旁以ASCII图形显示分支与合并历史。 -
git log --online --decorate --graph --all:会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。
1.4 撤销操作
- git commit --amend:有时候我们提交完了才发现漏掉几个文件没有添加,或者提交信息写错了,此时就可以使用该命令来重新提交。换句话说,就是新的提交替换了旧的提交。
- git reset HEAD .c:将暂存的 .c 文件取消暂存,变为修改未暂存的状态。
- git checkout – .c:该命令可以做到:不想保留 .c 文件的修改,将该文件还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)。但该命令同样也是一个危险的命令,你对该文件在本地的任何修改都会消失,Git 会用最近提交的版本覆盖掉它。除非你确实想清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。
1.5 远程仓库的使用
- git remote:查看你已经配置的远程仓库服务器,它会列出你指定的每一个远程服务器的简写。
- git remote -v:会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL 。如果你的远程仓库不止一个,该命令会将他们全部列出。
- git remote add :表示添加一个新的远程仓库,同时指定一个方便使用的简写。例如:
git remote add pb https://github.com/paulboone/ticgit ,现在你就可以在命令行中使用字符串pb来代替整个 URL。再者,如果你想要拉取 Paul 的仓库中但你没有的信息,可以直接运行git fetch pb 。 - git fetch:访问远程仓库,从中拉取所有你还没有的数据。必须注意:
git fetch 命令只会将数据下载到你的本地仓库,但是它并不会自动合并或者修改你当前的工作,当准备好时应必须手动将其合并你的工作。 - git pull:自动抓取后合并该远程分支到当前分支。通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前的所在的分支。
- git push :推送到远程仓库。当你想要分享你的项目时,必须将其推送到上游的。
- git remote show :查看某个远程仓库的更多信息。
- git remote rename:修改一个远程仓库的简写名。
- git remote remove/rm:删除一个远程仓库。
1.6 打标签
- git tag:列出标签。如果对某个标签感兴趣,可以直接运行
git tag -l/--list "v1.8.5" ,这样就可以获得标签中含有"v1.8.5" 版本系列的。 - git tag -a v1.4 -m “my version 1.4”:创建附注标签。
-m 选项指定了一条将会存储在标签中的信息。 - git tag v1.4-lw:创建轻量标签。轻量标签本质上是将提交校验和存储到一个文件中,但并没有保存任何其他的信息。
- git tag -a v1.2 <某个提交版本>:给某个版本打上v1.2的标签。
- git push origin :将创建完标签后你必须显示地推送标签到共享服务器。
- git push origin --tags:将所有 不在远程仓库服务器上的标签全部传送到那里,这样,当其他人从仓库克隆或者拉取,他们也能得到你的那些标签。
- git tag -d :删除你本地仓库上的标签。改命令不会从任何远程仓库中移除这个标签。
- git push origin --delete :删除远程仓库中的对应的标签。
- git checkout :检出标签。其实就是转换分支。如果你想查看某个标签所指向的文件版本,可以使用改命令,但是这会使你的仓库处于“分离头指针(detached HEAD)”的状态。
二、Git分支简介
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。在进行提交操作时,Git 会保存一个提交对象(commit object)。该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象。
2.1 分支的新建与合并–分支管理
- git branch testing:创建 testing 新分支。
- git branch:会得到当前所有分支的一个列表,而在某个分支上的
* 代表目前所在的分支,也就是HEAD 指针所指向的分支。 - git branch -v:查看每一个分支的最后一次提交。
- git branch --merged:查看哪些分支已经合并到当前分支。
- git branch --no-merged:查看所有包含未合并工作的分支。
- HEAD:表示在 Git 中,它是一个指针,指向当前所在的本地分支(译注:将
HEAD 想象为当前分支的别名)。 - git checkout testing:表示切换到新建的testing分支上去,此时
HEAD 就指向 testing 分支了。 - git checkout -b test:表示创建一个新分支test,并立即切换过去。
- git merge hotfix:将 hotfix 分支与当前分支合并。
- git branch -d hotfix:删除 hotfix 分支。
-D 选项表示强制删除。
-
遇到冲突时的分支合并:如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 分支的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突: $ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
-
解决思路:此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。
-
你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。 -
任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。出现冲突的文件会包含一些特殊区段,看起来像下面这个样子: <<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。
2.2 远程分支
- git ls-remote :显示地获得远程引用的完整列表。
- git remote show :获得远程分支的更多的信息。
- git push :显示地推送远端的某个分支上。例如:
git push origin serverfix 。等同于git push origin serverfix:serverfix ,推送本地的severfix 分支作为远程仓库的severfix 分支。 - git fetch:从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。 它只会获取数据然后让你自己合并。
- git fetch origin:抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本,只有再运行
git merge origin/serverfix 命令,将这些工作合并到当前所在的分支,才能编辑。 - git pull:查找当前分支所跟踪的服务器与分支, 从服务器上抓取数据然后尝试合并入那个远程分支。在大多数情况下它的含义是一个
git fetch 紧接着一个 git merge 命令。 - git checkout -b severfix origin/serverfix:建立自己的
serverfix 分支,并且起点位于origin/severfix 。 - git branch -vv:查看设置的所有跟踪分支。
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
这里可以看到 iss53 分支正在跟踪 origin/iss53 并且 “ahead” 是 2,意味着本地有两个提交还没有推送到服务器上。 也能看到 master 分支正在跟踪 origin/master 分支并且是最新的。 接下来可以看到 serverfix 分支正在跟踪 teamone 服务器上的 server-fix-good 分支并且领先 3 落后 1, 意味着服务器上有一次提交还没有合并入同时本地有三次提交还没有推送。 最后看到 testing 分支并没有跟踪任何远程分支。需要重点注意的一点是这些数字的值来自于你从每个服务器上最后一次抓取的数据。 这个命令并没有连接服务器,它只会告诉你关于本地缓存的服务器数据。
如果想要统计最新的领先与落后数字,需要在运行此命令前抓取所有的远程仓库。 可以像这样做:
$ git fetch --all; git branch -vv
- git push origin --delete serverfix:删除远程
serverfix 分支。
2.3 Git分支–变基
-
变基的原理:使用rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像"重新播放"一样。例如: $ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
它的原理:首先找到这两个分支(即当前分支 experiment 、变基操作的目标基底分支 master ) 的最近共同祖先 C2 ,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件, 然后将当前分支指向目标基底 C3 , 最后以此将之前另存为临时文件的修改依序应用。如下图
?
现在回到了master 分支上,进行一次快进合并。
$ git checkout master
$ git merge experiment
?
? 当你在查看一个经过变基的分支的历史记录时会发现,尽管实际工作上是并行的,但是它们看上去就像是串行的一样,提交的历史是一条直线没有分叉。
? 一般我们这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁–例如向某个其他人维护的项目贡献代码时。 在这种情况下,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 origin/master 上,然后再向主项目提交修改。 这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。
? 请注意,无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。
-
git rebase :直接将主题分支变基到目标分支上。这样能够省去你先切换到server 分支,再对其执行变基命令的多个步骤。例如:git rebase master server ,表示将server 分支中的修改变基到master 上;然后就可以快速合并主分支master 了:git checkout master; git merge server ,至此,就将server 分支中的修改全部整合至master 主分支里了。随后就可以删除该server 分支了:git branch -d server 。这样一来,整体上的提交历史就变成了一条直线了。 -
git rebase -i HEAD~3:如果想要修改最近三次提交信息。在 HEAD~3..HEAD 范围内的每一个修改了提交信息的提交及其 所有后裔 都会被重写。 -
变基的风险:变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。应当遵守的一条准则:如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。 -
git pull --rebase:因为git pull 将相同的内容又重新合并了一次,生成了一个新的提交,而使用--rebase 选项并不会产生一个commit 提交,而是直接将别的分支直接重放,不会多出你所不知道的commit ,使得commit 看起来很自然。
? 如果你只对不会离开你电脑的提交执行变基,那就不会有事。 如果你对已经推送过的提交执行变基,但别人没有基于它的提交,那么也不会有事。 如果你对已经推送至共用仓库的提交上执行变基命令,并因此丢失了一些别人的开发所基于的提交, 那你就有大麻烦了,你的同事也会因此鄙视你。
三、服务器上的Git
3.1 协议
Git 可以使用四种不同的协议来传输资料:本地协议(Local),HTTP 协议,SSH(Secure Shell)协议及 Git 协议。
-
本地协议:
最基本的就是 本地协议(Local protocol) ,其中的远程版本库就是同一主机上的另一个目录。如果你使用共享文件系统,就可以从本地版本库克隆(clone)、推送(push)以及拉取(pull)。 像这样去克隆一个版本库或者增加一个远程到现有的项目中,使用版本库路径作为 URL。 例如,克隆一个本地版本库,可以执行如下的命令:git clone /srv/git/project.git 。
优点:基于文件系统的版本库的优点是简单,并且直接使用了现有的文件权限和网络访问权限。
缺点:通常共享文件系统比较难配置,并且比起基本的网络连接访问,这不方便从多个位置访问。 如果你想从家里推送内容,必须先挂载一个远程磁盘,相比网络连接的访问方式,配置不方便,速度也慢。
-
HTTP协议:
? Git 通过 HTTP 通信有两种模式,分别为智能 HTTP 协议和哑 HTTP 协议。这个新的 HTTP 协议因为其简单、智能变的十分流行。 新版本的 HTTP 协议一般被称为 智能HTTP 协议,旧版本的一般被称为 哑 HTTP 协议。
? 智能 HTTP 协议或许已经是最流行的使用 Git 的方式了,它即支持像 git:// 协议一样设置匿名服务, 也可以像 SSH 协议一样提供传输时的授权和加密。 而且只用一个 URL 就可以都做到,省去了为不同的需求设置不同的 URL。 如果你要推送到一个需要授权的服务器上(一般来讲都需要),服务器会提示你输入用户名和密码。 从服务器获取数据时也一样。例如:git clone https://github.com/schacon/simplegit
智能 HTTP 协议的优点:
? 不同的访问方式只需要一个 URL 以及服务器只在需要授权时提示输入授权信息,这两个简便性让终端用户使用 Git 变得非常简单。 相比 SSH 协议,可以使用用户名/密码授权是一个很大的优势,这样用户就不必须在使用 Git 之前先在本地生成 SSH 密钥对再把公钥上传到服务器。 对非资深的使用者,或者系统上缺少 SSH 相关程序的使用者,HTTP 协议的可用性是主要的优势。与 SSH 协议类似,HTTP 协议也非常快和高效。
智能 HTTP 协议的缺点:
? 在一些服务器上,架设 HTTPS 协议的服务端会比 SSH 协议的棘手一些。 除了这一点,用其他协议提供 Git 服务与智能 HTTP 协议相比就几乎没有优势了。
-
SSH协议:
? 架设 Git 服务器时常用 SSH 协议作为传输协议。 因为大多数环境下服务器已经支持通过 SSH 访问 —— 即使没有也很容易架设。 SSH 协议也是一个验证授权的网络协议;并且,因为其普遍性,架设和使用都很容易。
? 通过 SSH 协议克隆版本库,例如:git clone ssh://[user@]server/project.git 或者 git clone [user@]server:project.git 。这两种情况中,如果你不指定可选的用户名,那么 Git 会使用当前登录的用的名字。
优点:
? 首先,SSH 架设相对简单 —— SSH 守护进程很常见,多数管理员都有使用经验,并且多数操作系统都包含了它及相关的管理工具。 其次,通过 SSH 访问是安全的 —— 所有传输数据都要经过授权和加密。 最后,与 HTTPS 协议、Git 协议及本地协议一样,SSH 协议很高效,在传输前也会尽量压缩数据。
缺点:
? SSH 协议的缺点:在于它不支持匿名访问 Git 仓库。 如果你使用 SSH,那么即便只是读取数据,使用者也必须通过 SSH 访问你的主机, 这使得 SSH 协议不利于开源的项目,毕竟人们可能只想把你的仓库克隆下来查看。 如果你只在公司网络使用,SSH 协议可能是你唯一要用到的协议。 如果你要同时提供匿名只读访问和 SSH 协议,那么你除了为自己推送架设 SSH 服务以外, 还得架设一个可以让其他人访问的服务。
-
Git 协议:
? 要让版本库支持 Git 协议,需要先创建一个 git-daemon-export-ok 文件 —— 它是 Git 协议守护进程为这个版本库提供服务的必要条件 —— 但是除此之外没有任何安全措施。 要么谁都可以克隆这个版本库,要么谁也不能。 这意味着,通常不能通过 Git 协议推送。 由于没有授权机制,一旦你开放推送操作,意味着网络上知道这个项目 URL 的人都可以向项目推送数据。
优点:
? Git 协议是 Git 使用的网络传输协议里最快的。 如果你的项目有很大的访问量,或者你的项目很庞大并且不需要为写进行用户授权,架设 Git 守护进程来提供服务是不错的选择。 它使用与 SSH 相同的数据传输机制,但是省去了加密和授权的开销。
缺点:
? Git 协议缺点:是缺乏授权机制。 把 Git 协议作为访问项目版本库的唯一手段是不可取的。 一般的做法里,会同时提供 SSH 或者 HTTPS 协议的访问服务,只让少数几个开发者有推送(写)权限,其他人通过 git:// 访问只有读权限。
3.2 在服务器上搭建Git
- git clone --bare my_project my_project.git:通过克隆你的仓库
my_project 来创建一个新的裸仓库,裸仓库的目录名以.git 结尾。 - scp -r my_project.git user@git.example.com:/srv/git:复制你的裸仓库来创建一个新的仓库。
四、分布式 Git
4.1 分布式工作流程
集中式系统中通常使用的是单点协作模型——集中式工作流。 一个中心集线器,或者说 仓库,可以接受代码,所有人将自己的工作与之同步。 若干个开发者则作为节点,即中心仓库的消费者与中心仓库同步。
这意味着如果两个开发者从中心仓库克隆代码下来,同时作了一些修改,那么只有第一个开发者可以顺利地把数据推送回共享服务器。 第二个开发者在推送修改之前,必须先将第一个人的工作合并进来,这样才不会覆盖第一个人的修改。这种模式的工作流程的使用非常广泛,因为大多数人对其很熟悉也很习惯。
Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。 这种情形下通常会有个代表“官方”项目的权威的仓库。 要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。 接着你可以请求官方仓库的维护者拉取更新合并到主项目。 维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。
这是 GitHub 和 GitLab 等集线器式(hub-based)工具最常用的工作流程。人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。 这么做最主要的优点之一是:你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。 贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己的节奏工作。
这个流程的工作方式如下:
1、项目维护者推送到主仓库;
2、贡献者克隆此仓库,做出修改;
3、贡献者将数据推送到自己的公开仓库;
4、贡献者给维护者发送邮件,请求拉取自己的更新;
5、维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改;
6、维护者将合并后的修改推送到主仓库。
这其实是多仓库工作流程的变种。 一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 被称为 副主管(lieutenant) 的各个集成管理者分别负责集成项目中的特定部分。 所有这些副主管头上还有一位称为 主管(dictator) 的总集成管理者负责统筹。 主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。
整个工作流程:
1、普通开发者在自己的主题分支上工作,并根据master 分支进行变基。这里是主管推送的参考仓库的master 分支。
2、副主管将普通开发者的主题分支合并到自己的master 分支中。
3、主管将所有副主管的master 分支并入自己的master 分支中。
4、最后,主管将集成后的master 分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基。
这种工作流程并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。利用这种方式,项目总负责人(即主管)可以把大量分散的集成工作委托给不同的小组负责人分别处理,然后在不同时刻将大块的代码子集统筹起来,用于之后的整合。
4.2 向一个项目贡献
-
提交准则:
1、git diff --check:将会检查出可能的空白错误并将它们为你列出来。提交前运行改命令,这样就可以知道提交中是否包含空白的问题。
2、注意的点:尝试将每一个提交成为一个逻辑上的独立变更集,也就是,别进行一次巨大的提交,而是变成拆分为多个提交,并且在每一个小提交上附带一个有用的信息。
3、git log --no-merged:查看未合并的项目提交历史。
-
项目提交时常用命令:
1、git push origin master:推送至远端仓库的master 分支。
2、消息的基本格式:… fromref -> toref:oldref 的含义是推送前所指向的引用, newref 的含义是推送后所指向的引用, fromref 是将要被推送的本地引用的名字, toref 是将要被更新的远程引用的名字。例如:1edee6b..fbff5bc master -> master 。
3、git log --no-merges issue54…origin/master:issue54..origin/master 语法是一个日志过滤器,要求 Git 只显示所有在后面分支 (在本例中是 origin/master )但不在前面分支(在本例中是 issue54 )的提交的列表。
4、git push -u origin featureB:featureBee:将所有合并后的featureB 推送回服务器,,但她并不想直接推送她自己的 featureB 分支,而是直接推送至featureBee 分支。注意 -u 标记,这是 --set-upstream 的简写,该标记会为之后轻松地推送与拉取配置分支。
4.3 维护项目
- git apply /tmp/patch-ruby-client.patch:将该补丁整合应用到项目中。
- git apply --check 0001-seeing-if-this-helps-the-gem.patch:检查该
.patch 补丁文件是否可以顺利应用。 - git am 0001-limit-log-function.patch:将补丁合并应用在项目中,等价于
git apply 。 - git log contrib --not master:查看
contrib 分支中而不是master 分支中的提交日志。
五、GitHub
5.1 对 GitHub 项目作出贡献
6.2 GitHub - 对项目做出贡献
- GitHub流程:
- 派生一个项目(fork)
- 从
master 分支创建一个新的分支 - 提交一些修改来改进项目
- 将这个分支推送到 GitHub 上
- 创建一个拉取请求(pull request)
- 讨论,根据实际情况继续修改
- 项目的拥有者合并或关闭你的拉取请求
- 将更新后的
master 分支同步到你的派生中
六、Git 工具
- git add -i/–interactive:Git 进入一个交互式终端模式。当你在修改了大量文件后,希望将这些改动能拆分为若干提交而不是混杂在一起成为一个提交时,这个工具就很有用。通过这种方式,可以确保提交是逻辑上独立的变更集,同时也会使其他开发者在与你工作时很容易地审核。
- git add -p/–patch:将部分文件暂存
- git reset --patch:利用补丁的模式来重置文件
- git checkout --patch:部分检出文件
- git stash:贮藏工作。有时,当你在项目的一部分上已经工作一段时间后,所有东西都进入了混乱的状态, 而这时你想要切换到另一个分支做一点别的事情。贮藏(stash)会处理工作目录的脏的状态——即跟踪文件的修改与暂存的改动——然后将未完成的修改保存到一个栈上, 而你可以在任何时候重新应用这些改动(甚至在不同的分支上)。等价于
git stash push 。
--keep-index 选项表示:Git 不仅要贮藏所有已暂存的内容,同时还要将它们保留在索中;--include-untracked 或 -u 选项表示:Git 也会贮藏任何未跟踪文件。 然而,在贮藏中包含未跟踪的文件仍然不会包含明确 忽略 的文件。 要额外包含忽略的文件,请使用 --all 或 -a 选项;--patch 表示:Git 不会贮藏所有修改过的任何东西, 但是会交互式地提示哪些改动想要贮藏、哪些改动需要保存在工作目录中。 - git stash list:查看贮藏东西的列表
- git stash apply:将刚刚贮藏的工作重新应用。如果想要应用其中一个更旧的贮藏,可以通过名字指定它,像这样:
git stash apply stash@{2} 。 如果不指定一个贮藏,Git 认为指定的是最近的贮藏。--index 选项尝试应用暂存的修改; - git stash drop:移除某个贮藏的工作。等价于
git stash pop 。 - git stash branch :以你指定的分支名创建一个新分支,检出贮藏工作时所在的提交,重新在那应用工作,然后在应用成功后丢弃贮藏
- git clean:对于工作目录中一些工作或文件,你想做的也许不是贮藏而是移除。
七、Git 内部原理
当在一个新目录或已有目录执行 git init 时,Git 会创建一个 .git 目录。 这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。 本章探讨的所有内容,均位于这个目录内。 新初始化的 .git 目录的典型结构如下:
$ ls -F1
config
description
HEAD
hooks/
info/
objects/
refs/
- ? 随着 Git 版本的不同,该目录下可能还会包含其他内容。 不过对于一个全新的
git init 版本库,这将是你看到的默认结构。 description 文件仅供 GitWeb 程序使用,我们无需关心。 config 文件包含项目特有的配置选项。 info 目录包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns)。 hooks 目录包含客户端或服务端的钩子脚本(hook scripts)。 - 剩下的四个条目很重要:
HEAD 文件、(尚待创建的)index 文件,和 objects 目录、refs 目录。 它们都是 Git 的核心组成部分。 objects 目录存储所有数据内容;refs 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针; HEAD 文件指向目前被检出的分支;index 文件保存暂存区信息。
|