├── .gitignore ├── 01-introduction ├── 1-introduction.adoc ├── images │ ├── areas.png │ ├── centralized.png │ ├── deltas.png │ ├── distributed.png │ ├── git-osx-installer.png │ ├── local.png │ └── snapshots.png └── sections │ ├── about-version-control.adoc │ ├── basics.adoc │ ├── command-line.adoc │ ├── first-time-setup.adoc │ ├── help.adoc │ ├── history.adoc │ ├── installing.adoc │ └── summary.adoc ├── 02-git-basics ├── 1-git-basics.adoc ├── images │ └── lifecycle.png └── sections │ ├── aliases.adoc │ ├── getting-a-repository.adoc │ ├── recording-changes.adoc │ ├── remotes.adoc │ ├── summary.adoc │ ├── tagging.adoc │ ├── undoing.adoc │ └── viewing-history.adoc ├── 03-git-branching ├── 1-git-branching.adoc ├── images │ ├── advance-master.png │ ├── advance-testing.png │ ├── basic-branching-1.png │ ├── basic-branching-2.png │ ├── basic-branching-3.png │ ├── basic-branching-4.png │ ├── basic-branching-5.png │ ├── basic-branching-6.png │ ├── basic-merging-1.png │ ├── basic-merging-2.png │ ├── basic-rebase-1.png │ ├── basic-rebase-2.png │ ├── basic-rebase-3.png │ ├── basic-rebase-4.png │ ├── branch-and-history.png │ ├── checkout-master.png │ ├── commit-and-tree.png │ ├── commits-and-parents.png │ ├── head-to-master.png │ ├── head-to-testing.png │ ├── interesting-rebase-1.png │ ├── interesting-rebase-2.png │ ├── interesting-rebase-3.png │ ├── interesting-rebase-4.png │ ├── interesting-rebase-5.png │ ├── lr-branches-1.png │ ├── lr-branches-2.png │ ├── perils-of-rebasing-1.png │ ├── perils-of-rebasing-2.png │ ├── perils-of-rebasing-3.png │ ├── perils-of-rebasing-4.png │ ├── perils-of-rebasing-5.png │ ├── remote-branches-1.png │ ├── remote-branches-2.png │ ├── remote-branches-3.png │ ├── remote-branches-4.png │ ├── remote-branches-5.png │ ├── topic-branches-1.png │ ├── topic-branches-2.png │ └── two-branches.png └── sections │ ├── basic-branching-and-merging.adoc │ ├── branch-management.adoc │ ├── nutshell.adoc │ ├── rebasing.adoc │ ├── remote-branches.adoc │ ├── summary.adoc │ └── workflows.adoc ├── 04-git-server ├── 1-git-server.adoc ├── images │ ├── bitnami.png │ ├── git-instaweb.png │ ├── gitlab-broadcast.png │ ├── gitlab-groups.png │ ├── gitlab-menu.png │ └── gitlab-users.png └── sections │ ├── generating-ssh-key.adoc │ ├── git-daemon.adoc │ ├── git-on-a-server.adoc │ ├── gitlab.adoc │ ├── gitweb.adoc │ ├── hosted.adoc │ ├── protocols.adoc │ ├── setting-up-server.adoc │ ├── smart-http.adoc │ └── summary.adoc ├── 05-distributed-git ├── 1-distributed-git.adoc ├── images │ ├── benevolent-dictator.png │ ├── centralized_workflow.png │ ├── git-diff-check.png │ ├── integration-manager.png │ ├── large-merges-1.png │ ├── large-merges-2.png │ ├── managed-team-1.png │ ├── managed-team-2.png │ ├── managed-team-3.png │ ├── managed-team-flow.png │ ├── merging-workflows-1.png │ ├── merging-workflows-2.png │ ├── merging-workflows-3.png │ ├── merging-workflows-4 2.png │ ├── merging-workflows-4.png │ ├── merging-workflows-5.png │ ├── public-small-1.png │ ├── public-small-2.png │ ├── public-small-3.png │ ├── rebasing-1.png │ ├── rebasing-2.png │ ├── small-team-1.png │ ├── small-team-2.png │ ├── small-team-3.png │ ├── small-team-4.png │ ├── small-team-5.png │ ├── small-team-6.png │ ├── small-team-7.png │ └── small-team-flow.png └── sections │ ├── contributing.adoc │ ├── distributed-workflows.adoc │ ├── maintaining.adoc │ └── summary.adoc ├── 06-github ├── 1-github.adoc ├── callouts │ ├── 1.pdf │ ├── 1.png │ ├── 10.pdf │ ├── 10.png │ ├── 2.pdf │ ├── 2.png │ ├── 3.pdf │ ├── 3.png │ ├── 4.pdf │ ├── 4.png │ ├── 5.pdf │ ├── 5.png │ ├── 6.pdf │ ├── 6.png │ ├── 7.pdf │ ├── 7.png │ ├── 8.pdf │ ├── 8.png │ ├── 9.pdf │ └── 9.png ├── images │ ├── 2fa-1.png │ ├── account-settings.png │ ├── avatar-crop.png │ ├── blink-01-start.png │ ├── blink-02-pr.png │ ├── blink-03-pull-request-open.png │ ├── blink-04-email.png │ ├── blink-04-pr-comment.png │ ├── blink-05-general-comment.png │ ├── blink-06-final.png │ ├── blink-pull-request-open copy.png │ ├── blink-pull-request-open.png │ ├── collaborators.png │ ├── email-settings.png │ ├── emoji.png │ ├── forkbutton.png │ ├── hubot.png │ ├── maint-01-email.png │ ├── maint-02-merge.png │ ├── maint-03-email-resp.png │ ├── maint-04-target.png │ ├── maint-05-mentions.png │ ├── maint-06-unsubscribe.png │ ├── maint-07-notifications.png │ ├── maint-08-notifications-page.png │ ├── maint-09-contrib.png │ ├── maint-10-default-branch.png │ ├── maint-11-transfer.png │ ├── markdown-01-example.png │ ├── markdown-02-tasks.png │ ├── markdown-03-task-summary.png │ ├── markdown-04-fenced-code.png │ ├── markdown-05-quote.png │ ├── markdown-06-emoji-complete.png │ ├── markdown-07-emoji.png │ ├── markdown-08-drag-drop.png │ ├── mentions-01-syntax.png │ ├── mentions-02-render.png │ ├── mentions-03-closed.png │ ├── new-repo.png │ ├── neworg.png │ ├── newrepo.png │ ├── newrepoform.png │ ├── notifications.png │ ├── orgs-01-page.png │ ├── orgs-02-teams.png │ ├── orgs-03-audit.png │ ├── pr-01-fail.png │ ├── pr-02-merge-fix.png │ ├── reposettingslink.png │ ├── scripting-01-services.png │ ├── scripting-02-email-service.png │ ├── scripting-03-webhook.png │ ├── scripting-04-webhook-debug.png │ ├── scripting-05-access-token.png │ ├── scripting-06-comment.png │ ├── scripting-07-status.png │ ├── signup.png │ ├── ssh-keys.png │ └── your-profile.png └── sections │ ├── 1-setting-up-account.adoc │ ├── 2-contributing.adoc │ ├── 3-maintaining.adoc │ ├── 4-managing-organization.adoc │ ├── 5-scripting.adoc │ └── 6-summary.adoc ├── 07-git-tools ├── 1-git-tools.adoc ├── callouts │ ├── 1.pdf │ ├── 1.png │ ├── 10.pdf │ ├── 10.png │ ├── 2.pdf │ ├── 2.png │ ├── 3.pdf │ ├── 3.png │ ├── 4.pdf │ ├── 4.png │ ├── 5.pdf │ ├── 5.png │ ├── 6.pdf │ ├── 6.png │ ├── 7.pdf │ ├── 7.png │ ├── 8.pdf │ ├── 8.png │ ├── 9.pdf │ └── 9.png ├── git-credential-read-only ├── images │ ├── double-dot.png │ ├── replace1.png │ ├── replace2.png │ ├── replace3.png │ ├── replace4.png │ ├── replace5.png │ ├── rerere1.png │ ├── rerere2.png │ ├── rerere3.png │ ├── reset-checkout.png │ ├── reset-ex1.png │ ├── reset-ex2.png │ ├── reset-ex3.png │ ├── reset-ex4.png │ ├── reset-ex5.png │ ├── reset-ex6.png │ ├── reset-hard.png │ ├── reset-mixed.png │ ├── reset-path1.png │ ├── reset-path2.png │ ├── reset-path3.png │ ├── reset-soft.png │ ├── reset-squash-r1.png │ ├── reset-squash-r2.png │ ├── reset-squash-r3.png │ ├── reset-start.png │ ├── reset-workflow.png │ ├── undomerge-reset.png │ ├── undomerge-revert.png │ ├── undomerge-revert2.png │ ├── undomerge-revert3.png │ └── undomerge-start.png └── sections │ ├── advanced-merging.adoc │ ├── bundling.adoc │ ├── credentials.adoc │ ├── debugging.adoc │ ├── interactive-staging.adoc │ ├── replace.adoc │ ├── rerere.adoc │ ├── reset.adoc │ ├── revision-selection.adoc │ ├── rewriting-history.adoc │ ├── searching.adoc │ ├── signing.adoc │ ├── stashing-cleaning.adoc │ ├── submodules.adoc │ ├── subtree-merges.adoc │ └── summary.adoc ├── 08-customizing-git ├── 1-customizing-git.adoc ├── images │ ├── clean.png │ ├── p4merge.png │ └── smudge.png └── sections │ ├── attributes.adoc │ ├── config.adoc │ ├── hooks.adoc │ ├── policy.adoc │ └── summary.adoc ├── 09-git-and-other-scms ├── 1-git-and-other-scms.adoc ├── images │ ├── git-fusion-boot.png │ ├── git-fusion-perforce-graph.png │ └── git-tfs-ct.png └── sections │ ├── client-hg.adoc │ ├── client-p4.adoc │ ├── client-svn.adoc │ ├── client-tfs.adoc │ ├── git-client.adoc │ ├── git-migrate.adoc │ ├── import-custom.adoc │ ├── import-hg.adoc │ ├── import-p4.adoc │ ├── import-svn.adoc │ ├── import-tfs.adoc │ └── summary.adoc ├── 10-git-internals ├── 1-git-internals.adoc ├── images │ ├── data-model-1.png │ ├── data-model-2.png │ ├── data-model-3.png │ └── data-model-4.png └── sections │ ├── environment.adoc │ ├── maintenance.adoc │ ├── objects.adoc │ ├── packfiles.adoc │ ├── plumbing-porcelain.adoc │ ├── refs.adoc │ ├── refspec.adoc │ ├── summary.adoc │ └── transfer-protocols.adoc ├── A-git-in-other-environments ├── 1-git-other-environments.adoc ├── images │ ├── branch_widget_mac.png │ ├── branch_widget_win.png │ ├── egit.png │ ├── git-bash.png │ ├── git-gui.png │ ├── github_mac.png │ ├── github_win.png │ ├── gitk.png │ ├── posh-git.png │ ├── vs-1.png │ ├── vs-2.png │ ├── zsh-oh-my.png │ └── zsh-prompt.png └── sections │ ├── bash.adoc │ ├── eclipse.adoc │ ├── guis.adoc │ ├── powershell.adoc │ ├── summary.adoc │ ├── visualstudio.adoc │ └── zsh.adoc ├── B-embedding-git ├── 1-embedding-git.adoc ├── callouts │ ├── 1.pdf │ ├── 1.png │ ├── 10.pdf │ ├── 10.png │ ├── 2.pdf │ ├── 2.png │ ├── 3.pdf │ ├── 3.png │ ├── 4.pdf │ ├── 4.png │ ├── 5.pdf │ ├── 5.png │ ├── 6.pdf │ ├── 6.png │ ├── 7.pdf │ ├── 7.png │ ├── 8.pdf │ ├── 8.png │ ├── 9.pdf │ └── 9.png └── sections │ ├── command-line.adoc │ ├── jgit.adoc │ └── libgit2.adoc ├── C-git-commands └── 1-git-commands.adoc ├── README.adoc ├── SUMMARY.adoc ├── book.json ├── contributors.adoc ├── cover.jpg ├── cover_small.jpg ├── introduction.adoc └── preface.adoc /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .gitignore support plugin (hsz.mobi) 2 | *.~ 3 | *.tmp 4 | .idea/ 5 | _book/ 6 | *.swp 7 | *.edx 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /01-introduction/1-introduction.adoc: -------------------------------------------------------------------------------- 1 | [[_getting_started]] 2 | == 起步 3 | 4 | 本章关于开始学习 Git。 5 | 我们从介绍有关版本控制工具的一些背景知识开始,然后讲解如何在你的系统运行 Git,最后是关于如何设置 Git 开始你的工作。 6 | 通过本章的学习,你应该了解为什么 Git 这么流行,为什么你应该使用 Git 以及你应该如何设置以便使用 Git。 7 | -------------------------------------------------------------------------------- /01-introduction/images/areas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/areas.png -------------------------------------------------------------------------------- /01-introduction/images/centralized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/centralized.png -------------------------------------------------------------------------------- /01-introduction/images/deltas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/deltas.png -------------------------------------------------------------------------------- /01-introduction/images/distributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/distributed.png -------------------------------------------------------------------------------- /01-introduction/images/git-osx-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/git-osx-installer.png -------------------------------------------------------------------------------- /01-introduction/images/local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/local.png -------------------------------------------------------------------------------- /01-introduction/images/snapshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/01-introduction/images/snapshots.png -------------------------------------------------------------------------------- /01-introduction/sections/about-version-control.adoc: -------------------------------------------------------------------------------- 1 | === 关于版本控制 2 | 3 | (((version control))) 4 | 什么是“版本控制”?我为什么要关心它呢? 5 | 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 6 | 在本书所展示的例子中,我们对保存着软件源代码的文件作版本控制,但实际上,你可以对任何类型的文件进行版本控制。 7 | 8 | 如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 9 | 有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。 10 | 使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。 11 | 但额外增加的工作量却微乎其微。 12 | 13 | ==== 本地版本控制系统 14 | 15 | (((version control,local))) 16 | 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 17 | 这么做唯一的好处就是简单,但是特别容易犯错。 18 | 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。 19 | 20 | 为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。 21 | 22 | .本地版本控制. 23 | image::../images/local.png[本地版本控制图解] 24 | 25 | 其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。 26 | 甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 `rcs` 命令。 27 | 它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。 28 | 29 | ==== 集中化的版本控制系统 30 | 31 | (((version control,centralized))) 32 | 接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 33 | 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。 34 | 这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。(((CVS)))(((Subversion)))(((Perforce))) 35 | 多年以来,这已成为版本控制系统的标准做法。 36 | 37 | .集中化的版本控制. 38 | image::../images/centralized.png[集中化的版本控制图解] 39 | 40 | 这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 41 | 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 42 | 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。 43 | 44 | 事分两面,有好有坏。 45 | 这么做最显而易见的缺点是中央服务器的单点故障。 46 | 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。 47 | 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。 48 | 本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。 49 | 50 | ==== 分布式版本控制系统 51 | 52 | (((version control,distributed))) 53 | 于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 54 | 在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 55 | 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 56 | 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。 57 | 58 | .分布式版本控制. 59 | image::../images/distributed.png[分布式版本控制图解] 60 | 61 | 更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 62 | 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。 63 | -------------------------------------------------------------------------------- /01-introduction/sections/basics.adoc: -------------------------------------------------------------------------------- 1 | === Git 基础 2 | 3 | 那么,简单地说,Git 究竟是怎样的一个系统呢? 4 | 请注意接下来的内容非常重要,若你理解了 Git 的思想和基本工作原理,用起来就会知其所以然,游刃有余。 5 | 在开始学习 Git 的时候,请努力分清你对其它版本管理系统的已有认识,如 Subversion 和 Perforce 等;这么做能帮助你使用工具时避免发生混淆。 6 | Git 在保存和对待各种信息的时候与其它版本控制系统有很大差异,尽管操作起来的命令形式非常相近,理解这些差异将有助于防止你使用中的困惑。(((Subversion)))(((Perforce))) 7 | 8 | ==== 直接记录快照,而非差异比较 9 | 10 | Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方法。 11 | 概念上来区分,其它大部分系统以文件变更列表的方式存储信息。 12 | 这类系统(CVS、Subversion、Perforce、Bazaar 等等)将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。 13 | 14 | .存储每个文件与初始版本的差异. 15 | image::../images/deltas.png[存储每个文件与初始版本的差异。] 16 | 17 | Git 不按照以上方式对待或保存数据。 18 | 反之,Git 更像是把数据看作是对小型文件系统的一组快照。 19 | 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 20 | 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 21 | Git 对待数据更像是一个 *快照流*。 22 | 23 | .存储项目随时间改变的快照. 24 | image::../images/snapshots.png[Git 存储项目随时间改变的快照。] 25 | 26 | 这是 Git 与几乎所有其它版本控制系统的重要区别。 27 | 因此 Git 重新考虑了以前每一代版本控制系统延续下来的诸多方面。 28 | Git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不只是一个简单的 VCS。 29 | 稍后我们在<<_git_branching>>讨论 Git 分支管理时,将探究这种方式对待数据所能获得的益处。 30 | 31 | ==== 近乎所有操作都是本地执行 32 | 33 | 在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。 34 | 如果你习惯于所有操作都有网络延时开销的集中式版本控制系统,Git 在这方面会让你感到速度之神赐给了 Git 超凡的能量。 35 | 因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。 36 | 37 | 举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 38 | 你能立即看到项目历史。 39 | 如果你想查看当前版本与一个月前的版本之间引入的修改,Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。 40 | 41 | 这也意味着你离线或者没有 VPN 时,几乎可以进行任何操作。 42 | 如你在飞机或火车上想做些工作,你能愉快地提交,直到有网络连接时再上传。 43 | 如你回家后 VPN 客户端不正常,你仍能工作。 44 | 使用其它系统,做到如此是不可能或很费力的。 45 | 比如,用 Perforce,你没有连接服务器时几乎不能做什么事;用 Subversion 和 CVS,你能修改文件,但不能向数据库提交修改(因为你的本地数据库离线了)。 46 | 这看起来不是大问题,但是你可能会惊喜地发现它带来的巨大的不同。 47 | 48 | ==== Git 保证完整性 49 | 50 | Git 中所有数据在存储前都计算校验和,然后以校验和来引用。 51 | 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 52 | 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 53 | 若你在传送过程中丢失信息或损坏文件,Git 就能发现。 54 | 55 | Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。(((SHA-1))) 56 | 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。 57 | SHA-1 哈希看起来是这样: 58 | 59 | [source] 60 | ---- 61 | 24b9da6552252987aa493b52f8696cd6d3b00373 62 | ---- 63 | 64 | Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 65 | 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。 66 | 67 | ==== Git 一般只添加数据 68 | 69 | 你执行的 Git 操作,几乎只往 Git 数据库中增加数据。 70 | 很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 71 | 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容;但是一旦你提交快照到 Git 中,就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。 72 | 73 | 这使得我们使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。 74 | 更深度探讨 Git 如何保存数据及恢复丢失数据的话题,请参考<<_undoing>>。 75 | 76 | ==== 三种状态 77 | 78 | 好,请注意。 79 | 如果你希望后面的学习更顺利,记住下面这些关于 Git 的概念。 80 | Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。 81 | 已提交表示数据已经安全的保存在本地数据库中。 82 | 已修改表示修改了文件,但还没保存到数据库中。 83 | 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。 84 | 85 | 由此引入 Git 项目的三个工作区域的概念:Git 仓库、工作目录以及暂存区域。 86 | 87 | .工作目录、暂存区域以及 Git 仓库. 88 | image::../images/areas.png[工作目录、暂存区域以及 Git 仓库。] 89 | 90 | Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 91 | 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。 92 | 93 | 工作目录是对项目的某个版本独立提取出来的内容。 94 | 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。 95 | 96 | 暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。 97 | 有时候也被称作``索引'',不过一般说法还是叫暂存区域。 98 | 99 | 基本的 Git 工作流程如下: 100 | 101 | 1. 在工作目录中修改文件。 102 | 2. 暂存文件,将文件的快照放入暂存区域。 103 | 3. 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。 104 | 105 | 如果 Git 目录中保存着的特定版本文件,就属于已提交状态。 106 | 如果作了修改并已放入暂存区域,就属于已暂存状态。 107 | 如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。 108 | 在<<_git_basics_chapter>>一章,你会进一步了解这些状态的细节,并学会如何根据文件状态实施后续操作,以及怎样跳过暂存直接提交。 109 | -------------------------------------------------------------------------------- /01-introduction/sections/command-line.adoc: -------------------------------------------------------------------------------- 1 | === 命令行 2 | 3 | Git 有多种使用方式。 4 | 你可以使用原生的命令行模式,也可以使用 GUI 模式,这些 GUI 软件也能提供多种功能。 5 | 在本书中,我们将使用命令行模式。 6 | 这是因为首先,只有在命令行模式下你才能执行 Git 的 *所有* 命令,而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度。 7 | 如果你学会了在命令行下如何操作,那么你在操作 GUI 软件时应该也不会遇到什么困难,但是,反之则不成立。 8 | 此外,由于每个人的想法与侧重点不同,不同的人常常会安装不同的 GUI 软件,但 _所有_ 人一定会有命令行工具。 9 | 10 | 假如你是 Mac 用户,我们希望你懂得如何使用终端(Terminal);假如你是 Windows 用户,我们希望你懂得如何使用命令窗口(Command Prompt)或 PowerShell。 11 | 如果你尚未掌握以上技能,我们建议你先停下来快速学习一下,本书中的讲述和举例将用到这些技能。 12 | -------------------------------------------------------------------------------- /01-introduction/sections/first-time-setup.adoc: -------------------------------------------------------------------------------- 1 | [[_first_time]] 2 | === 初次运行 Git 前的配置 3 | 4 | 既然已经在系统上安装了 Git,你会想要做几件事来定制你的 Git 环境。 5 | 每台计算机上只需要配置一次,程序升级时会保留配置信息。 6 | 你可以在任何时候再次通过运行命令来修改它们。 7 | 8 | Git 自带一个 `git config` 的工具来帮助设置控制 Git 外观和行为的配置变量。(((git commands, config))) 9 | 这些变量存储在三个不同的位置: 10 | 11 | 1. `/etc/gitconfig` 文件: 包含系统上每一个用户及他们仓库的通用配置。 12 | 如果使用带有 `--system` 选项的 `git config` 时,它会从此文件读写配置变量。 13 | 2. `~/.gitconfig` 或 `~/.config/git/config` 文件:只针对当前用户。 14 | 可以传递 `--global` 选项让 Git 读写此文件。 15 | 3. 当前使用仓库的 Git 目录中的 `config` 文件(就是 `.git/config`):针对该仓库。 16 | 17 | 每一个级别覆盖上一级别的配置,所以 `.git/config` 的配置变量会覆盖 `/etc/gitconfig` 中的配置变量。 18 | 19 | 在 Windows 系统中,Git 会查找 `$HOME` 目录下(一般情况下是 `C:\Users\$USER`)的 `.gitconfig` 文件。 20 | Git 同样也会寻找 `/etc/gitconfig` 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。 21 | 22 | ==== 用户信息 23 | 24 | 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 25 | 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改: 26 | 27 | [source,console] 28 | ---- 29 | $ git config --global user.name "John Doe" 30 | $ git config --global user.email johndoe@example.com 31 | ---- 32 | 33 | 再次强调,如果使用了 `--global` 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 34 | 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 `--global` 选项的命令来配置。 35 | 36 | 很多 GUI 工具都会在第一次运行时帮助你配置这些信息。 37 | 38 | ==== 文本编辑器 39 | 40 | 既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 41 | 如果未配置,Git 会使用操作系统默认的文本编辑器,通常是 Vim。 42 | 如果你想使用不同的文本编辑器,例如 Emacs,可以这样做: 43 | 44 | [source,console] 45 | ---- 46 | $ git config --global core.editor emacs 47 | ---- 48 | 49 | [WARNING] 50 | ==== 51 | Vim 和 Emacs 是像 Linux 与 Mac 等基于 Unix 的系统上开发者经常使用的流行的文本编辑器。 52 | 如果你对这些编辑器都不是很了解或者你使用的是 Windows 系统,那么可能需要搜索如何在 Git 中配置你最常用的编辑器。 53 | 如果你不设置编辑器并且不知道 Vim 或 Emacs 是什么,当它们运行起来后你可能会被弄糊涂、不知所措。 54 | ==== 55 | 56 | ==== 检查配置信息 57 | 58 | 如果想要检查你的配置,可以使用 `git config --list` 命令来列出所有 Git 当时能找到的配置。 59 | 60 | [source,console] 61 | ---- 62 | $ git config --list 63 | user.name=John Doe 64 | user.email=johndoe@example.com 65 | color.status=auto 66 | color.branch=auto 67 | color.interactive=auto 68 | color.diff=auto 69 | ... 70 | ---- 71 | 72 | 你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:`/etc/gitconfig` 与 `~/.gitconfig`)。 73 | 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。 74 | 75 | 你可以通过输入 `git config `:(((git commands, config))) 来检查 Git 的某一项配置 76 | 77 | [source,console] 78 | ---- 79 | $ git config user.name 80 | John Doe 81 | ---- 82 | -------------------------------------------------------------------------------- /01-introduction/sections/help.adoc: -------------------------------------------------------------------------------- 1 | [[_git_help]] 2 | === 获取帮助 3 | 4 | 若你使用 Git 时需要获取帮助,有三种方法可以找到 Git 命令的使用手册: 5 | 6 | [source,console] 7 | ---- 8 | $ git help 9 | $ git --help 10 | $ man git- 11 | ---- 12 | 13 | 例如,要想获得 config 命令的手册,执行(((git commands, help))) 14 | 15 | [source,console] 16 | ---- 17 | $ git help config 18 | ---- 19 | 20 | 这些命令很棒,因为你随时随地可以使用而无需联网。 21 | 如果你觉得手册或者本书的内容还不够用,你可以尝试在 Freenode IRC 服务器( irc.freenode.net )的 `#git` 或 `#github` 频道寻求帮助。 22 | 这些频道经常有上百人在线,他们都精通 Git 并且乐于助人。(((IRC))) 23 | -------------------------------------------------------------------------------- /01-introduction/sections/history.adoc: -------------------------------------------------------------------------------- 1 | === Git 简史 2 | 3 | 同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。 4 | 5 | Linux 内核开源项目有着为数众广的参与者。(((Linux))) 6 | 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 7 | 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。(((BitKeeper))) 8 | 9 | 到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 10 | 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。(((Linus Torvalds))) 11 | 他们对新的系统制订了若干目标: 12 | 13 | * 速度 14 | * 简单的设计 15 | * 对非线性开发模式的强力支持(允许成千上万个并行开发的分支) 16 | * 完全分布式 17 | * 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量) 18 | 19 | 自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 20 | 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统(参见 <<_git_branching>>)。 21 | -------------------------------------------------------------------------------- /01-introduction/sections/installing.adoc: -------------------------------------------------------------------------------- 1 | === 安装 Git 2 | 3 | 在你开始使用 Git 前,需要将它安装在你的计算机上。 4 | 即便已经安装,最好将它升级到最新的版本。 5 | 你可以通过软件包或者其它安装程序来安装,或者下载源码编译安装。 6 | 7 | [NOTE] 8 | ==== 9 | 本书写作时使用的 Git 版本为 *2.0.0*。 10 | 我们使用的大部分命令仍然可以在很古老的 Git 版本上使用,但也有少部分命令不好用或者在旧版本中的行为有差异。 11 | 因为 Git 在保持向后兼容方便表现很好,本书使用的这些命令在 2.0 之后的版本应该有效。 12 | ==== 13 | 14 | ==== 在 Linux 上安装 15 | 16 | (((Linux, installing))) 17 | 如果你想在 Linux 上用二进制安装程序来安装 Git,可以使用发行版包含的基础软件包管理工具来安装。 18 | 如果以 Fedora 上为例,你可以使用 yum: 19 | 20 | [source,console] 21 | $ sudo yum install git 22 | 23 | 如果你在基于 Debian 的发行版上,请尝试用 apt-get: 24 | 25 | [source,console] 26 | $ sudo apt-get install git 27 | 28 | 要了解更多选择,Git 官方网站上有在各种 Unix 风格的系统上安装步骤,网址为 http://git-scm.com/download/linux[]。 29 | 30 | ==== 在 Mac 上安装 31 | 32 | (((Mac, installing))) 33 | 在 Mac 上安装 Git 有多种方式。 34 | 最简单的方法是安装 Xcode Command Line Tools。(((Xcode))) 35 | Mavericks (10.9) 或更高版本的系统中,在 Terminal 里尝试首次运行 'git' 命令即可。 36 | 如果没有安装过命令行开发者工具,将会提示你安装。 37 | 38 | 如果你想安装更新的版本,可以使用二进制安装程序。 39 | 官方维护的 OSX Git 安装程序可以在 Git 官方网站下载,网址为 http://git-scm.com/download/mac[]。 40 | 41 | .Git OS X 安装程序. 42 | image::../images/git-osx-installer.png[Git OS X 安装程序。] 43 | 44 | 你也可以将它作为 GitHub for Mac 的一部分来安装。 45 | 它们的图形化 Git 工具有一个安装命令行工具的选项。 46 | 你可以从 GitHub for Mac 网站下载该工具,网址为 http://mac.github.com[]。 47 | 48 | ==== 在 Windows 上安装 49 | 50 | 在 Windows 上安装 Git 也有几种安装方法。(((Windows, installing))) 51 | 官方版本可以在 Git 官方网站下载。 52 | 打开 http://git-scm.com/download/win[],下载会自动开始。 53 | 要注意这是一个名为 Git for Windows的项目(也叫做 msysGit),和 Git 是分别独立的项目;更多信息请访问 http://msysgit.github.io/[]。 54 | 55 | 另一个简单的方法是安装 GitHub for Windows。 56 | 该安装程序包含图形化和命令行版本的 Git。 57 | 它也能支持 Powershell,提供了稳定的凭证缓存和健全的 CRLF 设置。(((Powershell)))(((CRLF)))(((credential caching))) 58 | 稍后我们会对这方面有更多了解,现在只要一句话就够了,这些都是你所需要的。 59 | 你可以在 GitHub for Windows 网站下载,网址为 http://windows.github.com[]。 60 | 61 | 62 | ==== 从源代码安装 63 | 64 | 有人觉得从源码安装 Git 更实用,因为你能得到最新的版本。 65 | 二进制安装程序倾向于有一些滞后,当然近几年 Git 已经成熟,这个差异不再显著。 66 | 67 | 如果你想从源码安装 Git,需要安装 Git 依赖的库:curl、zlib、openssl、expat,还有libiconv。 68 | 如果你的系统上有 yum (如 Fedora)或者 apt-get(如基于 Debian 的系统),可以使用以下命令之一来安装最小化的依赖包来编译和安装 Git 的二进制版: 69 | 70 | [source,console] 71 | $ sudo yum install curl-devel expat-devel gettext-devel \ 72 | openssl-devel zlib-devel 73 | $ sudo apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \ 74 | libz-dev libssl-dev 75 | 76 | 为了能够添加更多格式的文档(如 doc, html, info),你需要安装以下的依赖包: 77 | 78 | [source,console] 79 | $ sudo yum install asciidoc xmlto docbook2x 80 | $ sudo apt-get install asciidoc xmlto docbook2x 81 | 82 | 当你安装好所有的必要依赖,你可以继续从几个地方来取得最新发布版本的 tar 包。 83 | 你可以从 Kernel.org 网站获取,网址为 https://www.kernel.org/pub/software/scm/git[],或从 GitHub 网站上的镜像来获得,网址为 https://github.com/git/git/releases[]。 84 | 通常在 GitHub 上的是最新版本,但 kernel.org 上包含有文件下载签名,如果你想验证下载正确性的话会用到。 85 | 86 | 接着,编译并安装: 87 | 88 | [source,console] 89 | $ tar -zxf git-2.0.0.tar.gz 90 | $ cd git-2.0.0 91 | $ make configure 92 | $ ./configure --prefix=/usr 93 | $ make all doc info 94 | $ sudo make install install-doc install-html install-info 95 | 96 | 完成后,你可以使用 Git 来获取 Git 的升级: 97 | 98 | [source,console] 99 | $ git clone git://git.kernel.org/pub/scm/git/git.git 100 | -------------------------------------------------------------------------------- /01-introduction/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 你应该已经对 Git 是什么、Git 与你可能正在使用的集中式版本控制系统有何区别等问题有了基本的了解。 4 | 现在,在你的个人系统中应该也有了一份能够工作的 Git 版本。 5 | 是时候开始学习有关 Git 的基础知识了。 6 | -------------------------------------------------------------------------------- /02-git-basics/1-git-basics.adoc: -------------------------------------------------------------------------------- 1 | [[_git_basics_chapter]] 2 | == Git 基础 3 | 4 | 假如你只能阅读一章来学习 Git,本章就是你的不二选择。 5 | 本章内容涵盖你在使用 Git 完成各种工作中将要使用的各种基本命令。 6 | 在学习完本章之后,你应该能够配置并初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交(commit)更改。 7 | 本章也将向你演示如何配置 Git 来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操作、如何浏览你的项目的历史版本以及不同提交(commits)间的差异、如何向你的远程仓库推送(push)以及如何从你的远程仓库拉取(pull)文件。 8 | -------------------------------------------------------------------------------- /02-git-basics/images/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/02-git-basics/images/lifecycle.png -------------------------------------------------------------------------------- /02-git-basics/sections/aliases.adoc: -------------------------------------------------------------------------------- 1 | [[_git_aliases]] 2 | === Git 别名 3 | 4 | (((aliases))) 5 | 在我们结束本章 Git 基础之前,正好有一个小技巧可以使你的 Git 体验更简单、容易、熟悉:别名。 6 | 我们不会在之后的章节中引用到或假定你使用过它们,但是你大概应该知道如何使用它们。 7 | 8 | Git 并不会在你输入部分命令时自动推断出你想要的命令。 9 | 如果不想每次都输入完整的 Git 命令,可以通过 `git config` 文件来轻松地为每一个命令设置一个别名。(((git commands, config))) 10 | 这里有一些例子你可以试试: 11 | 12 | [source,console] 13 | ---- 14 | $ git config --global alias.co checkout 15 | $ git config --global alias.br branch 16 | $ git config --global alias.ci commit 17 | $ git config --global alias.st status 18 | ---- 19 | 20 | 这意味着,当要输入 `git commit` 时,只需要输入 `git ci`。 21 | 随着你继续不断地使用 Git,可能也会经常使用其他命令,所以创建别名时不要犹豫。 22 | 23 | 在创建你认为应该存在的命令时这个技术会很有用。 24 | 例如,为了解决取消暂存文件的易用性问题,可以向 Git 中添加你自己的取消暂存别名: 25 | 26 | [source,console] 27 | ---- 28 | $ git config --global alias.unstage 'reset HEAD --' 29 | ---- 30 | 31 | 这会使下面的两个命令等价: 32 | 33 | [source,console] 34 | ---- 35 | $ git unstage fileA 36 | $ git reset HEAD -- fileA 37 | ---- 38 | 39 | 这样看起来更清楚一些。 40 | 通常也会添加一个 `last` 命令,像这样: 41 | 42 | [source,console] 43 | ---- 44 | $ git config --global alias.last 'log -1 HEAD' 45 | ---- 46 | 47 | 这样,可以轻松地看到最后一次提交: 48 | 49 | [source,console] 50 | ---- 51 | $ git last 52 | commit 66938dae3329c7aebe598c2246a8e6af90d04646 53 | Author: Josh Goebel 54 | Date: Tue Aug 26 19:48:51 2008 +0800 55 | 56 | test for current head 57 | 58 | Signed-off-by: Scott Chacon 59 | ---- 60 | 61 | 可以看出,Git 只是简单地将别名替换为对应的命令。 62 | 然而,你可能想要执行外部命令,而不是一个 Git 子命令。 63 | 如果是那样的话,可以在命令前面加入 `!` 符号。 64 | 如果你自己要写一些与 Git 仓库协作的工具的话,那会很有用。 65 | 我们现在演示将 `git visual` 定义为 `gitk` 的别名: 66 | 67 | [source,console] 68 | ---- 69 | $ git config --global alias.visual '!gitk' 70 | ---- 71 | -------------------------------------------------------------------------------- /02-git-basics/sections/getting-a-repository.adoc: -------------------------------------------------------------------------------- 1 | [[_getting_a_repo]] 2 | === 获取 Git 仓库 3 | 4 | 有两种取得 Git 项目仓库的方法。 5 | 第一种是在现有项目或目录下导入所有文件到 Git 中; 6 | 第二种是从一个服务器克隆一个现有的 Git 仓库。 7 | 8 | ==== 在现有目录中初始化仓库 9 | 10 | 如果你打算使用 Git 来对现有的项目进行管理,你只需要进入该项目目录并输入: 11 | 12 | [source,console] 13 | ---- 14 | $ git init 15 | ---- 16 | 17 | 该命令将创建一个名为 `.git` 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 18 | 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。 19 | (参见 <<_git_internals>> 来了解更多关于到底 `.git` 文件夹中包含了哪些文件的信息。)(((git commands, init))) 20 | 21 | 如果你是在一个已经存在文件的文件夹(而不是空文件夹)中初始化 Git 仓库来进行版本控制的话,你应该开始跟踪这些文件并提交。 22 | 你可通过 `git add` 命令来实现对指定文件的跟踪,然后执行 `git commit` 提交: 23 | 24 | [source,console] 25 | ---- 26 | $ git add *.c 27 | $ git add LICENSE 28 | $ git commit -m 'initial project version' 29 | ---- 30 | 31 | 稍后我们再逐一解释每一条指令的意思。 32 | 现在,你已经得到了一个实际维护(或者说是跟踪)着若干个文件的 Git 仓库。 33 | 34 | [[_git_cloning]] 35 | ==== 克隆现有的仓库 36 | 37 | 如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 `git clone` 命令。 38 | 如果你对其它的 VCS 系统(比如说Subversion)很熟悉,请留心一下你所使用的命令是"clone"而不是"checkout"。 39 | 这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。 40 | 当你执行 `git clone` 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。 41 | 事实上,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库(虽然可能会丢失某些服务器端的挂钩设置,但是所有版本的数据仍在,详见 <<_git_on_the_server>> )。 42 | 43 | 克隆仓库的命令格式是 `git clone [url]` 。(((git commands, clone))) 44 | 比如,要克隆 Git 的可链接库 libgit2,可以用下面的命令: 45 | 46 | [source,console] 47 | ---- 48 | $ git clone https://github.com/libgit2/libgit2 49 | ---- 50 | 51 | 这会在当前目录下创建一个名为 ``libgit2'' 的目录,并在这个目录下初始化一个 `.git` 文件夹,从远程仓库拉取下所有数据放入 `.git` 文件夹,然后从中读取最新版本的文件的拷贝。 52 | 如果你进入到这个新建的 `libgit2` 文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。 53 | 如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以使用如下命令: 54 | 55 | [source,console] 56 | ---- 57 | $ git clone https://github.com/libgit2/libgit2 mylibgit 58 | ---- 59 | 60 | 这将执行与上一个命令相同的操作,不过在本地创建的仓库名字变为 `mylibgit`。 61 | 62 | Git 支持多种数据传输协议。 63 | 上面的例子使用的是 `https://` 协议,不过你也可以使用 `git://` 协议或者使用 SSH 传输协议,比如 `user@server:path/to/repo.git` 。 64 | <<_git_on_the_server>>将会介绍所有这些协议在服务器端如何配置使用,以及各种方式之间的利弊。 65 | -------------------------------------------------------------------------------- /02-git-basics/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 现在,你可以完成所有基本的 Git 本地操作-创建或者克隆一个仓库、做更改、暂存并提交这些更改、浏览你的仓库从创建到现在的所有更改的历史。 4 | 下一步,本书将介绍 Git 的杀手级特性:分支模型。 5 | -------------------------------------------------------------------------------- /02-git-basics/sections/tagging.adoc: -------------------------------------------------------------------------------- 1 | [[_git_tagging]] 2 | === 打标签 3 | 4 | (((tags))) 5 | 像其他版本控制系统(VCS)一样,Git 可以给历史中的某一个提交打上标签,以示重要。 6 | 比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 等等)。 7 | 在本节中,你将会学习如何列出已有的标签、如何创建新标签、以及不同类型的标签分别是什么。 8 | 9 | ==== 列出标签 10 | 11 | 在 Git 中列出已有的标签是非常简单直观的。 12 | 只需要输入 `git tag`:(((git commands, tag))) 13 | 14 | [source,console] 15 | ---- 16 | $ git tag 17 | v0.1 18 | v1.3 19 | ---- 20 | 21 | 这个命令以字母顺序列出标签;但是它们出现的顺序并不重要。 22 | 23 | 你也可以使用特定的模式查找标签。 24 | 例如,Git 自身的源代码仓库包含标签的数量超过 500 个。 25 | 如果只对 1.8.5 系列感兴趣,可以运行: 26 | 27 | [source,console] 28 | ---- 29 | $ git tag -l 'v1.8.5*' 30 | v1.8.5 31 | v1.8.5-rc0 32 | v1.8.5-rc1 33 | v1.8.5-rc2 34 | v1.8.5-rc3 35 | v1.8.5.1 36 | v1.8.5.2 37 | v1.8.5.3 38 | v1.8.5.4 39 | v1.8.5.5 40 | ---- 41 | 42 | ==== 创建标签 43 | 44 | Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。 45 | 46 | 一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。 47 | 48 | 然而,附注标签是存储在 Git 数据库中的一个完整对象。 49 | 它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证。 50 | 通常建议创建附注标签,这样你可以拥有以上所有信息;但是如果你只是想用一个临时的标签,或者因为某些原因不想要保存那些信息,轻量标签也是可用的。 51 | 52 | [[_annotated_tags]] 53 | ==== 附注标签 54 | 55 | (((tags, annotated))) 56 | 在 Git 中创建一个附注标签是很简单的。 57 | 最简单的方式是当你在运行 `tag` 命令时指定 `-a` 选项:(((git commands, tag))) 58 | 59 | [source,console] 60 | ---- 61 | $ git tag -a v1.4 -m 'my version 1.4' 62 | $ git tag 63 | v0.1 64 | v1.3 65 | v1.4 66 | ---- 67 | 68 | `-m` 选项指定了一条将会存储在标签中的信息。 69 | 如果没有为附注标签指定一条信息,Git 会运行编辑器要求你输入信息。 70 | 71 | 通过使用 `git show` 命令可以看到标签信息与对应的提交信息: 72 | 73 | [source,console] 74 | ---- 75 | $ git show v1.4 76 | tag v1.4 77 | Tagger: Ben Straub 78 | Date: Sat May 3 20:19:12 2014 -0700 79 | 80 | my version 1.4 81 | 82 | commit ca82a6dff817ec66f44342007202690a93763949 83 | Author: Scott Chacon 84 | Date: Mon Mar 17 21:52:11 2008 -0700 85 | 86 | changed the version number 87 | ---- 88 | 89 | 输出显示了打标签者的信息、打标签的日期时间、附注信息,然后显示具体的提交信息。 90 | 91 | ==== 轻量标签 92 | 93 | (((tags, lightweight))) 94 | 另一种给提交打标签的方式是使用轻量标签。 95 | 轻量标签本质上是将提交校验和存储到一个文件中 - 没有保存任何其他信息。 96 | 创建轻量标签,不需要使用 `-a`、`-s` 或 `-m` 选项,只需要提供标签名字: 97 | 98 | [source,console] 99 | ---- 100 | $ git tag v1.4-lw 101 | $ git tag 102 | v0.1 103 | v1.3 104 | v1.4 105 | v1.4-lw 106 | v1.5 107 | ---- 108 | 109 | 这时,如果在标签上运行 `git show`,你不会看到额外的标签信息。(((git commands, show))) 110 | 命令只会显示出提交信息: 111 | 112 | [source,console] 113 | ---- 114 | $ git show v1.4-lw 115 | commit ca82a6dff817ec66f44342007202690a93763949 116 | Author: Scott Chacon 117 | Date: Mon Mar 17 21:52:11 2008 -0700 118 | 119 | changed the version number 120 | ---- 121 | 122 | ==== 后期打标签 123 | 124 | 你也可以对过去的提交打标签。 125 | 假设提交历史是这样的: 126 | 127 | [source,console] 128 | ---- 129 | $ git log --pretty=oneline 130 | 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' 131 | a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support 132 | 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing 133 | 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' 134 | 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function 135 | 4682c3261057305bdd616e23b64b0857d832627b added a todo file 136 | 166ae0c4d3f420721acbb115cc33848dfcc2121a started write support 137 | 9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile 138 | 964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo 139 | 8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme 140 | ---- 141 | 142 | 现在,假设在 v1.2 时你忘记给项目打标签,也就是在 ``updated rakefile'' 提交。 143 | 你可以在之后补上标签。 144 | 要在那个提交上打标签,你需要在命令的末尾指定提交的校验和(或部分校验和): 145 | 146 | [source,console] 147 | ---- 148 | $ git tag -a v1.2 9fceb02 149 | ---- 150 | 151 | 可以看到你已经在那次提交上打上标签了:(((git commands, tag))) 152 | 153 | [source,console] 154 | ---- 155 | $ git tag 156 | v0.1 157 | v1.2 158 | v1.3 159 | v1.4 160 | v1.4-lw 161 | v1.5 162 | 163 | $ git show v1.2 164 | tag v1.2 165 | Tagger: Scott Chacon 166 | Date: Mon Feb 9 15:32:16 2009 -0800 167 | 168 | version 1.2 169 | commit 9fceb02d0ae598e95dc970b74767f19372d61af8 170 | Author: Magnus Chacon 171 | Date: Sun Apr 27 20:43:35 2008 -0700 172 | 173 | updated rakefile 174 | ... 175 | ---- 176 | 177 | [[_sharing_tags]] 178 | ==== 共享标签 179 | 180 | 默认情况下,`git push` 命令并不会传送标签到远程仓库服务器上。(((git commands, push))) 181 | 在创建完标签后你必须显式地推送标签到共享服务器上。 182 | 这个过程就像共享远程分支一样 - 你可以运行 `git push origin [tagname]`。 183 | 184 | [source,console] 185 | ---- 186 | $ git push origin v1.5 187 | Counting objects: 14, done. 188 | Delta compression using up to 8 threads. 189 | Compressing objects: 100% (12/12), done. 190 | Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done. 191 | Total 14 (delta 3), reused 0 (delta 0) 192 | To git@github.com:schacon/simplegit.git 193 | * [new tag] v1.5 -> v1.5 194 | ---- 195 | 196 | 如果想要一次性推送很多标签,也可以使用带有 `--tags` 选项的 `git push` 命令。 197 | 这将会把所有不在远程仓库服务器上的标签全部传送到那里。 198 | 199 | [source,console] 200 | ---- 201 | $ git push origin --tags 202 | Counting objects: 1, done. 203 | Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done. 204 | Total 1 (delta 0), reused 0 (delta 0) 205 | To git@github.com:schacon/simplegit.git 206 | * [new tag] v1.4 -> v1.4 207 | * [new tag] v1.4-lw -> v1.4-lw 208 | ---- 209 | 210 | 现在,当其他人从仓库中克隆或拉取,他们也能得到你的那些标签。 211 | 212 | ==== 检出标签 213 | 214 | 在 Git 中你并不能真的检出一个标签,因为它们并不能像分支一样来回移动。 215 | 如果你想要工作目录与仓库中特定的标签版本完全一样,可以使用 `git checkout -b [branchname] [tagname]` 在特定的标签上创建一个新分支: 216 | 217 | [source,console] 218 | ---- 219 | $ git checkout -b version2 v2.0.0 220 | Switched to a new branch 'version2' 221 | ---- 222 | 223 | 当然,如果在这之后又进行了一次提交,`version2` 分支会因为改动向前移动了,那么 `version2` 分支就会和 `v2.0.0` 标签稍微有些不同,这时就应该当心了。 224 | -------------------------------------------------------------------------------- /02-git-basics/sections/undoing.adoc: -------------------------------------------------------------------------------- 1 | [[_undoing]] 2 | === 撤消操作 3 | 4 | 在任何一个阶段,你都有可能想要撤消某些操作。 5 | 这里,我们将会学习几个撤消你所做修改的基本工具。 6 | 注意,有些撤消操作是不可逆的。 7 | 这是在使用 Git 的过程中,会因为操作失误而导致之前的工作丢失的少有的几个地方之一。 8 | 9 | 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 10 | 此时,可以运行带有 `--amend` 选项的提交命令尝试重新提交: 11 | 12 | [source,console] 13 | ---- 14 | $ git commit --amend 15 | ---- 16 | 17 | 这个命令会将暂存区中的文件提交。 18 | 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。 19 | 20 | 文本编辑器启动后,可以看到之前的提交信息。 21 | 编辑后保存会覆盖原来的提交信息。 22 | 23 | 例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作: 24 | 25 | [source,console] 26 | ---- 27 | $ git commit -m 'initial commit' 28 | $ git add forgotten_file 29 | $ git commit --amend 30 | ---- 31 | 32 | 最终你只会有一个提交 - 第二次提交将代替第一次提交的结果。 33 | 34 | [[_unstaging]] 35 | ==== 取消暂存的文件 36 | 37 | 接下来的两个小节演示如何操作暂存区域与工作目录中已修改的文件。 38 | 这些命令在修改文件状态的同时,也会提示如何撤消操作。 39 | 例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交,但是却意外地输入了 `git add *` 暂存了它们两个。 40 | 如何只取消暂存两个中的一个呢? 41 | `git status` 命令提示了你: 42 | 43 | [source,console] 44 | ---- 45 | $ git add * 46 | $ git status 47 | On branch master 48 | Changes to be committed: 49 | (use "git reset HEAD ..." to unstage) 50 | 51 | renamed: README.md -> README 52 | modified: CONTRIBUTING.md 53 | ---- 54 | 55 | 在 ``Changes to be committed'' 文字正下方,提示使用 `git reset HEAD ...` 来取消暂存。 56 | 所以,我们可以这样来取消暂存 `CONTRIBUTING.md` 文件: 57 | 58 | [source,console] 59 | ---- 60 | $ git reset HEAD CONTRIBUTING.md 61 | Unstaged changes after reset: 62 | M CONTRIBUTING.md 63 | $ git status 64 | On branch master 65 | Changes to be committed: 66 | (use "git reset HEAD ..." to unstage) 67 | 68 | renamed: README.md -> README 69 | 70 | Changes not staged for commit: 71 | (use "git add ..." to update what will be committed) 72 | (use "git checkout -- ..." to discard changes in working directory) 73 | 74 | modified: CONTRIBUTING.md 75 | ---- 76 | 77 | 这个命令有点儿奇怪,但是起作用了。 78 | `CONTRIBUTING.md` 文件已经是修改未暂存的状态了。 79 | 80 | [NOTE] 81 | ===== 82 | 虽然在调用时加上 `--hard` 选项**可以**令 `git reset` 成为一个危险的命令(译注:可能导致工作目录中所有当前进度丢失!),但本例中工作目录内的文件并不会被修改。 83 | 不加选项地调用 `git reset` 并不危险 — 它只会修改暂存区域。 84 | ===== 85 | 86 | 到目前为止这个神奇的调用就是你需要对 `git reset` 命令了解的全部。我们将会在 <<_git_reset>> 中了解 `reset` 的更多细节以及如何掌握它做一些真正有趣的事。 87 | 88 | ==== 撤消对文件的修改 89 | 90 | 如果你并不想保留对 `CONTRIBUTING.md` 文件的修改怎么办? 91 | 你该如何方便地撤消修改 - 将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)? 92 | 幸运的是,`git status` 也告诉了你应该如何做。 93 | 在最后一个例子中,未暂存区域是这样: 94 | 95 | [source,console] 96 | ---- 97 | Changes not staged for commit: 98 | (use "git add ..." to update what will be committed) 99 | (use "git checkout -- ..." to discard changes in working directory) 100 | 101 | modified: CONTRIBUTING.md 102 | ---- 103 | 104 | 它非常清楚地告诉了你如何撤消之前所做的修改。 105 | 让我们来按照提示执行: 106 | 107 | [source,console] 108 | ---- 109 | $ git checkout -- CONTRIBUTING.md 110 | $ git status 111 | On branch master 112 | Changes to be committed: 113 | (use "git reset HEAD ..." to unstage) 114 | 115 | renamed: README.md -> README 116 | 117 | ---- 118 | 119 | 可以看到那些修改已经被撤消了。 120 | 121 | [IMPORTANT] 122 | ===== 123 | 你需要知道 `git checkout -- [file]` 是一个危险的命令,这很重要。 124 | 你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。 125 | 除非你确实清楚不想要那个文件了,否则不要使用这个命令。 126 | ===== 127 | 128 | 如果你仍然想保留对那个文件做出的修改,但是现在仍然需要撤消,我们将会在 <<_git_branching>> 介绍保存进度与分支;这些通常是更好的做法。 129 | 130 | 记住,在 Git 中任何 __已提交的__ 东西几乎总是可以恢复的。 131 | 甚至那些被删除的分支中的提交或使用 `--amend` 选项覆盖的提交也可以恢复(阅读 <<_data_recovery>> 了解数据恢复)。 132 | 然而,任何你未提交的东西丢失后很可能再也找不到了。 133 | -------------------------------------------------------------------------------- /03-git-branching/1-git-branching.adoc: -------------------------------------------------------------------------------- 1 | [[_git_branching]] 2 | == Git 分支 3 | 4 | (((branches))) 5 | 几乎所有的版本控制系统都以某种形式支持分支。 6 | 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。 7 | 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费很多时间。 8 | 9 | 有人把 Git 的分支模型称为它的``必杀技特性'',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 10 | 为何 Git 的分支模型如此出众呢? 11 | Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 12 | 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 13 | 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。 14 | -------------------------------------------------------------------------------- /03-git-branching/images/advance-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/advance-master.png -------------------------------------------------------------------------------- /03-git-branching/images/advance-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/advance-testing.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-1.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-2.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-3.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-4.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-5.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-branching-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-branching-6.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-merging-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-merging-1.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-merging-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-merging-2.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-rebase-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-rebase-1.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-rebase-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-rebase-2.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-rebase-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-rebase-3.png -------------------------------------------------------------------------------- /03-git-branching/images/basic-rebase-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/basic-rebase-4.png -------------------------------------------------------------------------------- /03-git-branching/images/branch-and-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/branch-and-history.png -------------------------------------------------------------------------------- /03-git-branching/images/checkout-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/checkout-master.png -------------------------------------------------------------------------------- /03-git-branching/images/commit-and-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/commit-and-tree.png -------------------------------------------------------------------------------- /03-git-branching/images/commits-and-parents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/commits-and-parents.png -------------------------------------------------------------------------------- /03-git-branching/images/head-to-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/head-to-master.png -------------------------------------------------------------------------------- /03-git-branching/images/head-to-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/head-to-testing.png -------------------------------------------------------------------------------- /03-git-branching/images/interesting-rebase-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/interesting-rebase-1.png -------------------------------------------------------------------------------- /03-git-branching/images/interesting-rebase-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/interesting-rebase-2.png -------------------------------------------------------------------------------- /03-git-branching/images/interesting-rebase-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/interesting-rebase-3.png -------------------------------------------------------------------------------- /03-git-branching/images/interesting-rebase-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/interesting-rebase-4.png -------------------------------------------------------------------------------- /03-git-branching/images/interesting-rebase-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/interesting-rebase-5.png -------------------------------------------------------------------------------- /03-git-branching/images/lr-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/lr-branches-1.png -------------------------------------------------------------------------------- /03-git-branching/images/lr-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/lr-branches-2.png -------------------------------------------------------------------------------- /03-git-branching/images/perils-of-rebasing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/perils-of-rebasing-1.png -------------------------------------------------------------------------------- /03-git-branching/images/perils-of-rebasing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/perils-of-rebasing-2.png -------------------------------------------------------------------------------- /03-git-branching/images/perils-of-rebasing-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/perils-of-rebasing-3.png -------------------------------------------------------------------------------- /03-git-branching/images/perils-of-rebasing-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/perils-of-rebasing-4.png -------------------------------------------------------------------------------- /03-git-branching/images/perils-of-rebasing-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/perils-of-rebasing-5.png -------------------------------------------------------------------------------- /03-git-branching/images/remote-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/remote-branches-1.png -------------------------------------------------------------------------------- /03-git-branching/images/remote-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/remote-branches-2.png -------------------------------------------------------------------------------- /03-git-branching/images/remote-branches-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/remote-branches-3.png -------------------------------------------------------------------------------- /03-git-branching/images/remote-branches-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/remote-branches-4.png -------------------------------------------------------------------------------- /03-git-branching/images/remote-branches-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/remote-branches-5.png -------------------------------------------------------------------------------- /03-git-branching/images/topic-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/topic-branches-1.png -------------------------------------------------------------------------------- /03-git-branching/images/topic-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/topic-branches-2.png -------------------------------------------------------------------------------- /03-git-branching/images/two-branches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/03-git-branching/images/two-branches.png -------------------------------------------------------------------------------- /03-git-branching/sections/branch-management.adoc: -------------------------------------------------------------------------------- 1 | [[_branch_management]] 2 | === 分支管理 3 | 4 | (((branches, managing))) 5 | 现在已经创建、合并、删除了一些分支,让我们看看一些常用的分支管理工具。 6 | 7 | `git branch` 命令不只是可以创建与删除分支。(((git commands, branch))) 8 | 如果不加任何参数运行它,会得到当前所有分支的一个列表: 9 | 10 | [source,console] 11 | ---- 12 | $ git branch 13 | iss53 14 | * master 15 | testing 16 | ---- 17 | 18 | 注意 `master` 分支前的 `*` 字符:它代表现在检出的那一个分支(也就是说,当前 `HEAD` 指针所指向的分支)。 19 | 这意味着如果在这时候提交,`master` 分支将会随着新的工作向前移动。 20 | 如果需要查看每一个分支的最后一次提交,可以运行 `git branch -v` 命令: 21 | 22 | [source,console] 23 | ---- 24 | $ git branch -v 25 | iss53 93b412c fix javascript issue 26 | * master 7a98805 Merge branch 'iss53' 27 | testing 782fd34 add scott to the author list in the readmes 28 | ---- 29 | 30 | `--merged` 与 `--no-merged` 这两个有用的选项可以过滤这个列表中已经合并或尚未合并到当前分支的分支。 31 | 如果要查看哪些分支已经合并到当前分支,可以运行 `git branch --merged`: 32 | 33 | [source,console] 34 | ---- 35 | $ git branch --merged 36 | iss53 37 | * master 38 | ---- 39 | 40 | 因为之前已经合并了 `iss53` 分支,所以现在看到它在列表中。 41 | 在这个列表中分支名字前没有 `*` 号的分支通常可以使用 `git branch -d` 删除掉;你已经将它们的工作整合到了另一个分支,所以并不会失去任何东西。 42 | 43 | 查看所有包含未合并工作的分支,可以运行 `git branch --no-merged`: 44 | 45 | [source,console] 46 | ---- 47 | $ git branch --no-merged 48 | testing 49 | ---- 50 | 51 | 这里显示了其他分支。 52 | 因为它包含了还未合并的工作,尝试使用 `git branch -d` 命令删除它时会失败: 53 | 54 | [source,console] 55 | ---- 56 | $ git branch -d testing 57 | error: The branch 'testing' is not fully merged. 58 | If you are sure you want to delete it, run 'git branch -D testing'. 59 | ---- 60 | 61 | 如果真的想要删除分支并丢掉那些工作,如同帮助信息里所指出的,可以使用 `-D` 选项强制删除它。 62 | -------------------------------------------------------------------------------- /03-git-branching/sections/nutshell.adoc: -------------------------------------------------------------------------------- 1 | [[_git_branches_overview]] 2 | === 分支简介 3 | 4 | 为了真正理解 Git 处理分支的方式,我们需要回顾一下 Git 是如何保存数据的。 5 | 6 | 或许你还记得 <<_getting_started>> 的内容,Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。 7 | 8 | 在进行提交操作时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 9 | 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象, 10 | 11 | 为了说得更加形象,我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。 12 | 暂存操作会为每一个文件计算校验和(使用我们在 <<_getting_started>> 中提到的 SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交: 13 | 14 | [source,console] 15 | ---- 16 | $ git add README test.rb LICENSE 17 | $ git commit -m 'The initial commit of my project' 18 | ---- 19 | 20 | 当使用 `git commit` 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。 21 | 随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。(((git commands, commit))) 22 | 23 | 现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。 24 | 25 | .首次提交对象及其树结构 26 | image::../images/commit-and-tree.png[首次提交对象及其树结构.] 27 | 28 | 做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。 29 | 30 | .提交对象及其父对象 31 | image::../images/commits-and-parents.png[提交对象及其父对象.] 32 | 33 | Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 34 | Git 的默认分支名字是 `master`。 35 | 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 `master` 分支。 36 | 它会在每次的提交操作中自动向前移动。 37 | 38 | [NOTE] 39 | ==== 40 | Git 的 ``master'' 分支并不是一个特殊分支。(((master))) 41 | 它就跟其它分支完全没有区别。 42 | 之所以几乎每一个仓库都有 master 分支,是因为 `git init` 命令默认创建它,并且大多数人都懒得去改动它。 43 | ==== 44 | 45 | .分支及其提交历史 46 | image::../images/branch-and-history.png[分支及其提交历史.] 47 | 48 | [[_create_new_branch]] 49 | ==== 分支创建 50 | 51 | (((branches, creating))) 52 | Git 是怎么创建新分支的呢? 53 | 很简单,它只是为你创建了一个可以移动的新的指针。 54 | 比如,创建一个 testing 分支, 55 | 你需要使用 `git branch` 命令:(((git commands, branch))) 56 | 57 | [source,console] 58 | ---- 59 | $ git branch testing 60 | ---- 61 | 62 | 这会在当前所在的提交对象上创建一个指针。 63 | 64 | .两个指向相同提交历史的分支 65 | image::../images/two-branches.png[两个指向相同提交历史的分支。] 66 | 67 | 那么,Git 又是怎么知道当前在哪一个分支上呢? 68 | 也很简单,它有一个名为 `HEAD` 的特殊指针。 69 | 请注意它和许多其它版本控制系统(如 Subversion 或 CVS)里的 `HEAD` 概念完全不同。 70 | 在 Git 中,它是一个指针,指向当前所在的本地分支(译注:将 `HEAD` 想象为当前分支的别名)。 71 | 在本例中,你仍然在 `master` 分支上。 72 | 因为 `git branch` 命令仅仅 _创建_ 一个新分支,并不会自动切换到新分支中去。 73 | 74 | .HEAD 指向当前所在的分支 75 | image::../images/head-to-master.png[HEAD 指向当前所在的分支.] 76 | 77 | 你可以简单地使用 `git log` 命令查看各个分支当前所指的对象。 78 | 提供这一功能的参数是 `--decorate`。 79 | 80 | [source,console] 81 | ---- 82 | $ git log --oneline --decorate 83 | f30ab (HEAD, master, testing) add feature #32 - ability to add new 84 | 34ac2 fixed bug #1328 - stack overflow under certain conditions 85 | 98ca9 initial commit of my project 86 | ---- 87 | 88 | 正如你所见,当前 ``master'' 和 ``testing'' 分支均指向校验和以 `f30ab` 开头的提交对象。 89 | 90 | [[_switching_branches]] 91 | ==== 分支切换 92 | 93 | (((branches, switching))) 94 | 要切换到一个已存在的分支,你需要使用 `git checkout` 命令。(((git commands, checkout))) 95 | 我们现在切换到新创建的 `testing` 分支去: 96 | 97 | [source,console] 98 | ---- 99 | $ git checkout testing 100 | ---- 101 | 102 | 这样 `HEAD` 就指向 `testing` 分支了。 103 | 104 | .HEAD 指向当前所在的分支 105 | image::../images/head-to-testing.png[HEAD 指向当前所在的分支.] 106 | 107 | 那么,这样的实现方式会给我们带来什么好处呢? 108 | 现在不妨再提交一次: 109 | 110 | [source,console] 111 | ---- 112 | $ vim test.rb 113 | $ git commit -a -m 'made a change' 114 | ---- 115 | 116 | .HEAD 分支随着提交操作自动向前移动 117 | image::../images/advance-testing.png[HEAD 分支随着提交操作自动向前移动.] 118 | 119 | 如图所示,你的 `testing` 分支向前移动了,但是 `master` 分支却没有,它仍然指向运行 `git checkout` 时所指的对象。 120 | 这就有意思了,现在我们切换回 `master` 分支看看: 121 | 122 | [source,console] 123 | ---- 124 | $ git checkout master 125 | ---- 126 | 127 | .检出时 HEAD 随之移动 128 | image::../images/checkout-master.png[检出时 HEAD 随之移动.] 129 | 130 | 这条命令做了两件事。 131 | 一是使 HEAD 指回 `master` 分支,二是将工作目录恢复成 `master` 分支所指向的快照内容。 132 | 也就是说,你现在做修改的话,项目将始于一个较旧的版本。 133 | 本质上来讲,这就是忽略 `testing` 分支所做的修改,以便于向另一个方向进行开发。 134 | 135 | [NOTE] 136 | .分支切换会改变你工作目录中的文件 137 | ==== 138 | 在切换分支时,一定要注意你工作目录里的文件会被改变。 139 | 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 140 | 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。 141 | ==== 142 | 143 | 我们不妨再稍微做些修改并提交: 144 | 145 | [source,console] 146 | ---- 147 | $ vim test.rb 148 | $ git commit -a -m 'made other changes' 149 | ---- 150 | 151 | 现在,这个项目的提交历史已经产生了分叉(参见 <>)。 152 | 因为刚才你创建了一个新分支,并切换过去进行了一些工作,随后又切换回 master 分支进行了另外一些工作。 153 | 上述两次改动针对的是不同分支:你可以在不同分支间不断地来回切换和工作,并在时机成熟时将它们合并起来。 154 | 而所有这些工作,你需要的命令只有 `branch`、`checkout` 和 `commit`。 155 | 156 | [[divergent_history]] 157 | .项目分叉历史 158 | image::../images/advance-master.png[项目分叉历史.] 159 | 160 | 你可以简单地使用 `git log` 命令查看分叉历史。 161 | 运行 `git log --oneline --decorate --graph --all` ,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。 162 | 163 | [source,console] 164 | ---- 165 | $ git log --oneline --decorate --graph --all 166 | * c2b9e (HEAD, master) made other changes 167 | | * 87ab2 (testing) made a change 168 | |/ 169 | * f30ab add feature #32 - ability to add new formats to the 170 | * 34ac2 fixed bug #1328 - stack overflow under certain conditions 171 | * 98ca9 initial commit of my project 172 | ---- 173 | 174 | 由于 Git 的分支实质上仅是包含所指对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以它的创建和销毁都异常高效。 175 | 创建一个新分支就像是往一个文件中写入 41 个字节(40 个字符和 1 个换行符),如此的简单能不快吗? 176 | 177 | 这与过去大多数版本控制系统形成了鲜明的对比,它们在创建分支时,将所有的项目文件都复制一遍,并保存到一个特定的目录。 178 | 完成这样繁琐的过程通常需要好几秒钟,有时甚至需要好几分钟。所需时间的长短,完全取决于项目的规模。而在 Git 中,任何规模的项目都能在瞬间创建新分支。 179 | 同时,由于每次提交都会记录父对象,所以寻找恰当的合并基础(译注:即共同祖先)也是同样的简单和高效。 180 | 这些高效的特性使得 Git 鼓励开发人员频繁地创建和使用分支。 181 | 182 | 接下来,让我们看看为什么你应该这么做? 183 | -------------------------------------------------------------------------------- /03-git-branching/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 我们已经讲完了 Git 分支与合并的基础知识。 4 | 你现在应该能自如地创建并切换至新分支、在不同分支之间切换以及合并本地分支。 5 | 你现在应该也能通过推送你的分支至共享服务以分享它们、使用共享分支与他人协作以及在共享之前使用变基操作合并你的分支。 6 | 下一章,我们将要讲到,如果你想要运行自己的 Git 仓库托管服务器,你需要知道些什么。 7 | -------------------------------------------------------------------------------- /03-git-branching/sections/workflows.adoc: -------------------------------------------------------------------------------- 1 | === 分支开发工作流 2 | 3 | 现在你已经学会新建和合并分支,那么你可以或者应该用它来做些什么呢? 4 | 在本节,我们会介绍一些常见的利用分支进行开发的工作流程。而正是由于分支管理的便捷,才衍生出这些典型的工作模式,你可以根据项目实际情况选择一种用用看。 5 | 6 | ==== 长期分支 7 | 8 | (((branches, long-running))) 9 | 因为 Git 使用简单的三方合并,所以就算在一段较长的时间内,反复把一个分支合并入另一个分支,也不是什么难事。 10 | 也就是说,在整个项目开发周期的不同阶段,你可以同时拥有多个开放的分支;你可以定期地把某些特性分支合并入其他分支中。 11 | 12 | 许多使用 Git 的开发者都喜欢使用这种方式来工作,比如只在 `master` 分支上保留完全稳定的代码——有可能仅仅是已经发布或即将发布的代码。 13 | 他们还有一些名为 `develop` 或者 `next` 的平行分支,被用来做后续开发或者测试稳定性——这些分支不必保持绝对稳定,但是一旦达到稳定状态,它们就可以被合并入 `master` 分支了。 14 | 这样,在确保这些已完成的特性分支(短期分支,比如之前的 `iss53` 分支)能够通过所有测试,并且不会引入更多 bug 之后,就可以合并入主干分支中,等待下一次的发布。 15 | 16 | 事实上我们刚才讨论的,是随着你的提交而不断右移的指针。 17 | 稳定分支的指针总是在提交历史中落后一大截,而前沿分支的指针往往比较靠前。 18 | 19 | .渐进稳定分支的线性图 20 | image::../images/lr-branches-1.png[渐进稳定分支的线性图。] 21 | 22 | 通常把他们想象成流水线(work silos)可能更好理解一点,那些经过测试考验的提交会被遴选到更加稳定的流水线上去。 23 | 24 | [[lrbranch_b]] 25 | .渐进稳定分支的流水线(“silo”)视图 26 | image::../images/lr-branches-2.png[渐进稳定分支的工作流(“silo”)视图。] 27 | 28 | 你可以用这种方法维护不同层次的稳定性。 29 | 一些大型项目还有一个 `proposed`(建议) 或 `pu: proposed updates`(建议更新)分支,它可能因包含一些不成熟的内容而不能进入 `next` 或者 `master` 分支。 30 | 这么做的目的是使你的分支具有不同级别的稳定性;当它们具有一定程度的稳定性后,再把它们合并入具有更高级别稳定性的分支中。 31 | 再次强调一下,使用多个长期分支的方法并非必要,但是这么做通常很有帮助,尤其是当你在一个非常庞大或者复杂的项目中工作时。 32 | 33 | [[_topic_branch]] 34 | ==== 特性分支 35 | 36 | (((branches, topic))) 37 | 特性分支对任何规模的项目都适用。 38 | 特性分支是一种短期分支,它被用来实现单一特性或其相关工作。 39 | 也许你从来没有在其他的版本控制系统(`VCS`)上这么做过,因为在那些版本控制系统中创建和合并分支通常很费劲。 40 | 然而,在 Git 中一天之内多次创建、使用、合并、删除分支都很常见。 41 | 42 | 你已经在上一节中你创建的 `iss53` 和 `hotfix` 特性分支中看到过这种用法。 43 | 你在上一节用到的特性分支(`iss53` 和 `hotfix` 分支)中提交了一些更新,并且在它们合并入主干分支之后,你又删除了它们。 44 | 这项技术能使你快速并且完整地进行上下文切换(context-switch)——因为你的工作被分散到不同的流水线中,在不同的流水线中每个分支都仅与其目标特性相关,因此,在做代码审查之类的工作的时候就能更加容易地看出你做了哪些改动。 45 | 你可以把做出的改动在特性分支中保留几分钟、几天甚至几个月,等它们成熟之后再合并,而不用在乎它们建立的顺序或工作进度。 46 | 47 | 考虑这样一个例子,你在 `master` 分支上工作到 `C1`,这时为了解决一个问题而新建 `iss91` 分支,在 `iss91` 分支上工作到 `C4`,然而对于那个问题你又有了新的想法,于是你再新建一个 `iss91v2` 分支试图用另一种方法解决那个问题,接着你回到 `master` 分支工作了一会儿,你又冒出了一个不太确定的想法,你便在 `C10` 的时候新建一个 `dumbidea` 分支,并在上面做些实验。 48 | 你的提交历史看起来像下面这个样子: 49 | 50 | .拥有多个特性分支的提交历史 51 | image::../images/topic-branches-1.png[拥有多个特性分支的提交历史。] 52 | 53 | 现在,我们假设两件事情:你决定使用第二个方案来解决那个问题,即使用在 `iss91v2` 分支中方案;另外,你将 `dumbidea` 分支拿给你的同事看过之后,结果发现这是个惊人之举。 54 | 这时你可以抛弃 `iss91` 分支(即丢弃 `C5` 和 `C6` 提交),然后把另外两个分支合并入主干分支。 55 | 最终你的提交历史看起来像下面这个样子: 56 | 57 | .合并了 `dumbidea` 和 `iss91v2` 分支之后的提交历史 58 | image::../images/topic-branches-2.png[合并了 `dumbidea` 和 `iss91v2` 分支之后的提交历史。] 59 | 60 | 我们将会在 <<_distributed_git>> 中向你揭示更多有关分支工作流的细节,因此,请确保你阅读完那个章节之后,再来决定你的下个项目要使用什么样的分支策略(branching scheme)。 61 | 62 | 请牢记,当你做这么多操作的时候,这些分支全部都存于本地。 63 | 当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中 —— 没有与服务器发生交互。 64 | -------------------------------------------------------------------------------- /04-git-server/1-git-server.adoc: -------------------------------------------------------------------------------- 1 | == 服务器上的 Git 2 | 3 | (((serving repositories))) 4 | 到目前为止,你应该已经有办法使用 Git 来完成日常工作。 5 | 然而,为了使用 Git 协作功能,你还需要有远程的 Git 仓库。 6 | 尽管在技术上你可以从个人仓库进行推送(push)和拉取(pull)来修改内容,但不鼓励使用这种方法,因为一不留心就很容易弄混其他人的进度。 7 | 此外,你希望你的合作者们即使在你的电脑未联机时亦能存取仓库 — 拥有一个更可靠的公用仓库十分有用。 8 | 因此,与他人合作的最佳方法即是建立一个你与合作者们都有权利访问,且可从那里推送和拉取资料的共用仓库。 9 | 10 | 架设一台 Git 服务器并不难。 11 | 首先,选择你希望服务器使用的通讯协议。 12 | 在本章第一节将介绍可用的协议以及各自优缺点。 13 | 下面一节将解释使用那些协议的典型设置及如何在你的服务器上运行。 14 | 最后,如果你不介意托管你的代码在其他人的服务器,且不想经历设置与维护自己服务器的麻烦,可以试试我们介绍的几个仓库托管服务。 15 | 16 | 如果你对架设自己的服务器没兴趣,可以跳到本章最后一节去看看如何申请一个代码托管服务的帐户然后继续下一章,我们会在那里讨论分散式源码控制环境的林林总总。 17 | 18 | 一个远程仓库通常只是一个裸仓库(_bare repository_)— 即一个没有当前工作目录的仓库。 19 | 因为该仓库仅仅作为合作媒介,不需要从磁碟检查快照;存放的只有 Git 的资料。 20 | 简单的说,裸仓库就是你专案目录内的 `.git` 子目录内容,不包含其他资料。 21 | -------------------------------------------------------------------------------- /04-git-server/images/bitnami.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/bitnami.png -------------------------------------------------------------------------------- /04-git-server/images/git-instaweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/git-instaweb.png -------------------------------------------------------------------------------- /04-git-server/images/gitlab-broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/gitlab-broadcast.png -------------------------------------------------------------------------------- /04-git-server/images/gitlab-groups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/gitlab-groups.png -------------------------------------------------------------------------------- /04-git-server/images/gitlab-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/gitlab-menu.png -------------------------------------------------------------------------------- /04-git-server/images/gitlab-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/04-git-server/images/gitlab-users.png -------------------------------------------------------------------------------- /04-git-server/sections/generating-ssh-key.adoc: -------------------------------------------------------------------------------- 1 | [[_generate_ssh_key]] 2 | === 生成 SSH 公钥 3 | 4 | (((SSH keys))) 5 | 如前所述,许多 Git 服务器都使用 SSH 公钥进行认证。 6 | 为了向 Git 服务器提供 SSH 公钥,如果某系统用户尚未拥有密钥,必须事先为其生成一份。 7 | 这个过程在所有操作系统上都是相似的。 8 | 首先,你需要确认自己是否已经拥有密钥。 9 | 默认情况下,用户的 SSH 密钥存储在其 `~/.ssh` 目录下。 10 | 进入该目录并列出其中内容,你便可以快速确认自己是否已拥有密钥: 11 | 12 | [source,console] 13 | ---- 14 | $ cd ~/.ssh 15 | $ ls 16 | authorized_keys2 id_dsa known_hosts 17 | config id_dsa.pub 18 | ---- 19 | 20 | 我们需要寻找一对以 `id_dsa` 或 `id_rsa` 命名的文件,其中一个带有 `.pub` 扩展名。 21 | `.pub` 文件是你的公钥,另一个则是私钥。 22 | 如果找不到这样的文件(或者根本没有 `.ssh` 目录),你可以通过运行 `ssh-keygen` 程序来创建它们。在 Linux/Mac 系统中,`ssh-keygen` 随 SSH 软件包提供;在 Windows 上,该程序包含于 MSysGit 软件包中。 23 | 24 | [source,console] 25 | ---- 26 | $ ssh-keygen 27 | Generating public/private rsa key pair. 28 | Enter file in which to save the key (/home/schacon/.ssh/id_rsa): 29 | Created directory '/home/schacon/.ssh'. 30 | Enter passphrase (empty for no passphrase): 31 | Enter same passphrase again: 32 | Your identification has been saved in /home/schacon/.ssh/id_rsa. 33 | Your public key has been saved in /home/schacon/.ssh/id_rsa.pub. 34 | The key fingerprint is: 35 | d0:82:24:8e:d7:f1:bb:9b:33:53:96:93:49:da:9b:e3 schacon@mylaptop.local 36 | ---- 37 | 38 | 首先 `ssh-keygen` 会确认密钥的存储位置(默认是 `.ssh/id_rsa`),然后它会要求你输入两次密钥口令。如果你不想在使用密钥时输入口令,将其留空即可。 39 | 40 | 现在,进行了上述操作的用户需要将各自的公钥发送给任意一个 Git 服务器管理员(假设服务器正在使用基于公钥的 SSH 验证设置)。 41 | 他们所要做的就是复制各自的 `.pub` 文件内容,并将其通过邮件发送。 42 | 公钥看起来是这样的: 43 | 44 | [source,console] 45 | ---- 46 | $ cat ~/.ssh/id_rsa.pub 47 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU 48 | GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 49 | Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA 50 | t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En 51 | mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx 52 | NrRFi9wrf+M7Q== schacon@mylaptop.local 53 | ---- 54 | 55 | 关于在多种操作系统中生成 SSH 密钥的更深入教程,请参阅 GitHub 的 SSH 密钥指南 https://help.github.com/articles/generating-ssh-keys[]。 56 | -------------------------------------------------------------------------------- /04-git-server/sections/git-daemon.adoc: -------------------------------------------------------------------------------- 1 | === Git 守护进程 2 | 3 | (((serving repositories, git protocol))) 4 | 接下来我们将通过 ``Git'' 协议建立一个基于守护进程的仓库。 5 | 对于快速且无需授权的 Git 数据访问,这是一个理想之选。 6 | 请注意,因为其不包含授权服务,任何通过该协议管理的内容将在其网络上公开。 7 | 8 | 如果运行在防火墙之外的服务器上,它应该只对那些公开的只读项目服务。 9 | 如果运行在防火墙之内的服务器上,它可用于支撑大量参与人员或自动系统(用于持续集成或编译的主机)只读访问的项目,这样可以省去逐一配置 SSH 公钥的麻烦。 10 | 11 | 无论何时,该 Git 协议都是相对容易设定的。 12 | 通常,你只需要以守护进程的形式运行该命令:(((git commands, daemon))) 13 | 14 | [source,console] 15 | ---- 16 | git daemon --reuseaddr --base-path=/opt/git/ /opt/git/ 17 | ---- 18 | 19 | `--reuseaddr` 允许服务器在无需等待旧连接超时的情况下重启,`--base-path` 选项允许用户在未完全指定路径的条件下克隆项目,结尾的路径将告诉 Git 守护进程从何处寻找仓库来导出。 20 | 如果有防火墙正在运行,你需要开放端口 9418 的通信权限。 21 | 22 | 你可以通过许多方式将该进程以守护进程的方式运行,这主要取决于你所使用的操作系统。 23 | 在一台 Ubuntu 机器上,你可以使用一份 Upstart 脚本。 24 | 因此,找到如下文件: 25 | 26 | [source,console] 27 | ---- 28 | /etc/event.d/local-git-daemon 29 | ---- 30 | 31 | 并添加下列脚本内容: 32 | 33 | [source,console] 34 | ---- 35 | start on startup 36 | stop on shutdown 37 | exec /usr/bin/git daemon \ 38 | --user=git --group=git \ 39 | --reuseaddr \ 40 | --base-path=/opt/git/ \ 41 | /opt/git/ 42 | respawn 43 | ---- 44 | 45 | 出于安全考虑,强烈建议使用一个对仓库拥有只读权限的用户身份来运行该守护进程 - 你可以创建一个新用户 'git-ro' 并且以该用户身份来运行守护进程。 46 | 为简便起见,我们将像 `git-shell` 一样,同样使用 'git' 用户来运行它。 47 | 48 | 当你重启机器时,你的 Git 守护进程将会自动启动,并且如果进程被意外结束它会自动重新运行。 49 | 为了在不重启的情况下直接运行,你可以运行以下命令: 50 | 51 | [source,console] 52 | ---- 53 | initctl start local-git-daemon 54 | ---- 55 | 56 | 在其他系统中,你可以使用 `sysvinit` 系统中的 `xinetd` 脚本,或者另外的方式来实现 - 只要你能够将其命令守护进程化并实现监控。 57 | 58 | 接下来,你需要告诉 Git 哪些仓库允许基于服务器的无授权访问。 59 | 你可以在每个仓库下创建一个名为 `git-daemon-export-ok` 的文件来实现。 60 | 61 | [source,console] 62 | ---- 63 | $ cd /path/to/project.git 64 | $ touch git-daemon-export-ok 65 | ---- 66 | 67 | 该文件将允许 Git 提供无需授权的项目访问服务。 68 | -------------------------------------------------------------------------------- /04-git-server/sections/git-on-a-server.adoc: -------------------------------------------------------------------------------- 1 | [[_git_on_the_server]] 2 | === 在服务器上搭建 Git 3 | 4 | 现在我们将讨论如何在你自己的服务器上搭建 Git 服务来运行这些协议。 5 | 6 | [NOTE] 7 | ==== 8 | 这里我们将要演示在 Linux 服务器上进行一次基本且简化的安装所需的命令与步骤,当然在 Mac 或 Windows 服务器上同样可以运行这些服务。 9 | 事实上,在你的计算机基础架构中建立一个生产环境服务器,将不可避免的使用到不同的安全措施与操作系统工具。但是,希望你能从本节中获得一些必要的知识。 10 | ==== 11 | 12 | 在开始架设 Git 服务器前,需要把现有仓库导出为裸仓库——即一个不包含当前工作目录的仓库。 13 | 这通常是很简单的。 14 | 为了通过克隆你的仓库来创建一个新的裸仓库,你需要在克隆命令后加上 `--bare`选项(((git commands, clone, bare))) 15 | 按照惯例,裸仓库目录名以 .git 结尾,就像这样: 16 | 17 | [source,console] 18 | ---- 19 | $ git clone --bare my_project my_project.git 20 | Cloning into bare repository 'my_project.git'... 21 | done. 22 | ---- 23 | 24 | 现在,你的 `my_project.git` 目录中应该有 Git 目录的副本了。 25 | 26 | 整体上效果大致相当于 27 | 28 | [source,console] 29 | ---- 30 | $ cp -Rf my_project/.git my_project.git 31 | ---- 32 | 33 | 虽然在配置文件中有若干不同,但是对于你的目的来说,这两种方式都是一样的。 34 | 它只取出 Git 仓库自身,不要工作目录,然后特别为它单独创建一个目录。 35 | 36 | [[_bare_repo]] 37 | ==== 把裸仓库放到服务器上 38 | 39 | 既然你有了裸仓库的副本,剩下要做的就是把裸仓库放到服务器上并设置你的协议。 40 | 假设一个域名为 `git.example.com` 的服务器已经架设好,并可以通过 SSH 连接,你想把所有的 Git 仓库放在 `/opt/git` 目录下。 41 | 假设服务器上存在 `/opt/git/` 目录,你可以通过以下命令复制你的裸仓库来创建一个新仓库: 42 | 43 | [source,console] 44 | ---- 45 | $ scp -r my_project.git user@git.example.com:/opt/git 46 | ---- 47 | 48 | 此时,其他通过 SSH 连接这台服务器并对 `/opt/git` 目录拥有可读权限的使用者,通过运行以下命令就可以克隆你的仓库。 49 | 50 | [source,console] 51 | ---- 52 | $ git clone user@git.example.com:/opt/git/my_project.git 53 | ---- 54 | 55 | 如果一个用户,通过使用 SSH 连接到一个服务器,并且其对 `/opt/git/my_project.git` 目录拥有可写权限,那么他将自动拥有推送权限。 56 | 57 | 如果到该项目目录中运行 `git init` 命令,并加上 `--shared` 选项,那么 Git 会自动修改该仓库目录的组权限为可写。(((git commands, init, bare))) 58 | 59 | [source,console] 60 | ---- 61 | $ ssh user@git.example.com 62 | $ cd /opt/git/my_project.git 63 | $ git init --bare --shared 64 | ---- 65 | 66 | 由此可见,根据现有的 Git 仓库创建一个裸仓库,然后把它放上你和协作者都有 SSH 访问权的服务器是多么容易。 67 | 现在你们已经准备好在同一项目上展开合作了。 68 | 69 | 值得注意的是,这的确是架设一个几个人拥有连接权的 Git 服务的全部——只要在服务器上加入可以用 SSH 登录的帐号,然后把裸仓库放在大家都有读写权限的地方。 70 | 你已经准备好了一切,无需更多。 71 | 72 | 下面的几节中,你会了解如何扩展到更复杂的设定。 73 | 这些内容包含如何避免为每一个用户建立一个账户,给仓库添加公共读取权限,架设网页界面等等。 74 | 然而,请记住这一点,如果只是和几个人在一个私有项目上合作的话,__仅仅__ 是一个 SSH 服务器和裸仓库就足够了。 75 | 76 | ==== 小型安装 77 | 78 | 如果设备较少或者你只想在小型开发团队里尝试 Git ,那么一切都很简单。 79 | 架设 Git 服务最复杂的地方在于用户管理。 80 | 如果需要仓库对特定的用户可读,而给另一部分用户读写权限,那么访问和许可安排就会比较困难。 81 | 82 | ===== SSH 连接 83 | 84 | (((serving repositories, SSH))) 85 | 如果你有一台所有开发者都可以用 SSH 连接的服务器,架设你的第一个仓库就十分简单了,因为你几乎什么都不用做(正如我们上一节所说的)。 86 | 如果你想在你的仓库上设置更复杂的访问控制权限,只要使用服务器操作系统的普通的文件系统权限就行了。 87 | 88 | 如果需要团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户,那么提供 SSH 连接就是唯一的选择了。 89 | 我们假设用来共享仓库的服务器已经安装了 SSH 服务,而且你通过它访问服务器。 90 | 91 | 有几个方法可以使你给团队每个成员提供访问权。 92 | 第一个就是给团队里的每个人创建账号,这种方法很直接但也很麻烦。 93 | 或许你不会想要为每个人运行一次 `adduser` 并且设置临时密码。 94 | 95 | 第二个办法是在主机上建立一个 'git' 账户,让每个需要写权限的人发送一个 SSH 公钥,然后将其加入 git 账户的 `~/.ssh/authorized_keys` 文件。 96 | 这样一来,所有人都将通过 'git' 账户访问主机。 97 | 这一点也不会影响提交的数据——访问主机用的身份不会影响提交对象的提交者信息。 98 | 99 | 另一个办法是让 SSH 服务器通过某个 LDAP 服务,或者其他已经设定好的集中授权机制,来进行授权。 100 | 只要每个用户可以获得主机的 shell 访问权限,任何 SSH 授权机制你都可视为是有效的。 101 | -------------------------------------------------------------------------------- /04-git-server/sections/gitlab.adoc: -------------------------------------------------------------------------------- 1 | === GitLab 2 | 3 | (((serving repositories, GitLab)))(((GitLab))) 4 | 虽然 GitWeb 相当简单。 5 | 但如果你正在寻找一个更现代,功能更全的 Git 服务器,这里有几个开源的解决方案可供你选择安装。 6 | 因为 GitLab 是其中最出名的一个,我们将它作为示例并讨论它的安装和使用。 7 | 这比 GitWeb 要复杂的多并且需要更多的维护,但它的确是一个功能更全的选择。 8 | 9 | ==== 安装 10 | 11 | GitLab 是一个数据库支持的 web 应用,所以相比于其他 git 服务器,它的安装过程涉及到更多的东西。 12 | 幸运的是,这个过程有非常详细的文档说明和支持。 13 | 14 | 这里有一些可参考的方法帮你安装 GitLab 。 15 | 为了更快速的启动和运行,你可以下载虚拟机镜像或者在 https://bitnami.com/stack/gitlab[] 上获取一键安装包,同时调整配置使之符合你特定的环境。(((bitnami))) 16 | Bitnami 的一个优点在于它的登录界面(通过 alt-&rarr 键进入;);它会告诉你安装好的 GitLab 的 IP 地址以及默认的用户名和密码。 17 | 18 | [[bitnami]] 19 | .Bitnami GitLab 虚拟机登录界面。 20 | image::../images/bitnami.png[Bitnami GitLab 虚拟机登录界面。] 21 | 22 | 无论如何,跟着 GitLab 社区版的 readme 文件一步步来,你可以在这里找到它 https://gitlab.com/gitlab-org/gitlab-ce/tree/master[] 。 23 | 在这里你将会在主菜单中找到安装 GitLab 的帮助,一个可以在 Digital Ocean 上运行的虚拟机,以及 RPM 和 DEB 包(都是测试版)。 24 | 这里还有 ``非官方'' 的引导让 GitLab 运行在非标准的操作系统和数据库上,一个全手动的安装脚本,以及许多其他的话题。 25 | 26 | ==== 管理 27 | 28 | GitLab 的管理界面是通过网络进入的。 29 | 将你的浏览器转到已经安装 GitLab 的 主机名或 IP 地址,然后以管理员身份登录即可。 30 | 默认的用户名是 `admin@local.host`,默认的密码是 `5iveL!fe`(你会得到类似 请登录后尽快更换密码 的提示)。 31 | 登录后,点击主栏上方靠右位置的 ``Admin area'' 图标进行管理。 32 | 33 | [[gitlab_menu]] 34 | .GitLab 主栏的 ``Admin area'' 图标。 35 | image::../images/gitlab-menu.png[GitLab 主栏的 ``Admin area'' 图标。] 36 | 37 | ===== 使用者 38 | 39 | GitLab 上的用户指的是对应协作者的帐号。 40 | 用户帐号没有很多复杂的地方,主要是包含登录数据的用户信息集合。 41 | 每一个用户账号都有一个 *命名空间* ,即该用户项目的逻辑集合。 42 | 如果一个叫 +jane+ 的用户拥有一个名称是 +project+ 的项目,那么这个项目的 url 会是 http://server/jane/project[] 。 43 | 44 | [[gitlab_users]] 45 | .GitLab 用户管理界面。 46 | image::../images/gitlab-users.png[.GitLab 用户管理界面。] 47 | 48 | 移除一个用户有两种方法。 49 | ``屏蔽(Blocking)'' 一个用户阻止他登录 GitLab 实例,但是该用户命名空间下的所有数据仍然会被保存,并且仍可以通过该用户提交对应的登录邮箱链接回他的个人信息页。 50 | 51 | 而另一方面,``销毁(Destroying)'' 一个用户,会彻底的将他从数据库和文件系统中移除。 52 | 他命名空间下的所有项目和数据都会被删除,拥有的任何组也会被移除。 53 | 这显然是一个更永久且更具破坏力的行为,所以很少用到这种方法。 54 | 55 | [[_gitlab_groups_section]] 56 | ===== 组 57 | 58 | 一个 GitLab 的组是一些项目的集合,连同关于多少用户可以访问这些项目的数据。 59 | 每一个组都有一个项目命名空间(与用户一样),所以如果一个叫 +training+ 的组拥有一个名称是 +materials+ 的项目,那么这个项目的 url 会是 http://server/training/materials[] 。 60 | 61 | [[gitlab_groups]] 62 | .GitLab组 管理界面。 63 | image::../images/gitlab-groups.png[GitLab组 管理界面。] 64 | 65 | 每一个组都有许多用户与之关联,每一个用户对组中的项目以及组本身的权限都有级别区分。 66 | 权限的范围从 ``访客''(仅能提问题和讨论) 到 ``拥有者''(完全控制组、成员和项目)。 67 | 权限的种类太多以至于难以在这里一一列举,不过在 GitLab 的管理界面上有帮助链接。 68 | 69 | ===== 项目 70 | 71 | 一个 GitLab 的项目相当于 git 的版本库。 72 | 每一个项目都属于一个用户或者一个组的单个命名空间。 73 | 如果这个项目属于一个用户,那么这个拥有者对所有可以获取这个项目的人拥有直接管理权;如果这个项目属于一个组,那么该组中用户级别的权限也会起作用。 74 | 75 | 每一个项目都有一个可视级别,控制着谁可以看到这个项目页面和仓库。 76 | 如果一个项目是 _私有_ 的,这个项目的拥有者必须明确授权从而使特定的用户可以访问。 77 | 一个 _内部_ 的项目可以被所有登录的人看到,而一个 _公开_ 的项目则是对所有人可见的。 78 | 注意,这种控制既包括 git ``fetch'' 的使用也包括对项目 web 用户界面的访问。 79 | 80 | ===== 钩子 81 | 82 | GitLab 在项目和系统级别上都支持钩子程序。 83 | 对任意级别,当有相关事件发生时,GitLab 的服务器会执行一个包含描述性 JSON 数据的 HTTP 请求。 84 | 这是自动化连接你的 git 版本库和 GitLab 实例到其他的开发工具,比如 CI 服务器,聊天室,或者部署工具的一个极好方法。 85 | 86 | ==== 基本用途 87 | 88 | 你想要在 GitLab 做的第一件事就是建立一个新项目。 89 | 这通过点击工具栏上的 ``+'' 图标完成。 90 | 你会被要求填写项目名称,也就是这个项目所属的命名空间,以及它的可视层级。 91 | 绝大多数的设定并不是永久的,可以通过设置界面重新调整。 92 | 点击 ``Create Project'',你就完成了。 93 | 94 | 项目存在后,你可能会想将它与本地的 Git 版本库连接。 95 | 每一个项目都可以通过 HTTPS 或者 SSH 连接,任意两者都可以被用来配置远程 Git。 96 | 在项目主页的顶栏可以看到这个项目的 URLs。 97 | 对于一个存在的本地版本库,这个命令将会向主机位置添加一个叫 `gitlab` 的远程仓库: 98 | 99 | [source,console] 100 | ---- 101 | $ git remote add gitlab https://server/namespace/project.git 102 | ---- 103 | 104 | 如果你的本地没有版本库的副本,你可以这样做: 105 | 106 | [source,console] 107 | ---- 108 | $ git clone https://server/namespace/project.git 109 | ---- 110 | 111 | web 用户界面提供了几个有用的获取版本库信息的网页。 112 | 每一个项目的主页都显示了最近的活动,并且通过顶部的链接可以使你浏览项目文件以及提交日志。 113 | 114 | ==== 一起工作 115 | 116 | 在一个 GitLab 项目上一起工作的最简单方法就是赋予协作者对 git 版本库的直接 push 权限。 117 | 你可以通过项目设定的 ``Members(成员)'' 部分向一个项目添加写作者,并且将这个新的协作者与一个访问级别关联(不同的访问级别在 <<_gitlab_groups_section>> 中已简单讨论)。 118 | 通过赋予一个协作者 ``Developer(开发者)'' 或者更高的访问级别,这个用户就可以毫无约束地直接向版本库或者向分支进行提交。 119 | 120 | 另外一个让合作更解耦的方法就是使用合并请求。 121 | 它的优点在于让任何能够看到这个项目的协作者在被管控的情况下对这个项目作出贡献。 122 | 可以直接访问的协作者能够简单的创建一个分支,向这个分支进行提交,也可以开启一个向 `master` 或者其他任何一个分支的合并请求。 123 | 对版本库没有推送权限的协作者则可以 ``fork'' 这个版本库(即创建属于自己的这个库的副本),向 _那个_ 副本进行提交,然后从那个副本开启一个到主项目的合并请求。 124 | 这个模型使得项目拥有者完全控制着向版本库的提交,以及什么时候允许加入陌生协作者的贡献。 125 | 126 | 在 GitLab 中合并请求和问题是一个长久讨论的主要部分。 127 | 每一个合并请求都允许在提出改变的行进行讨论(它支持一个轻量级的代码审查),也允许对一个总体性话题进行讨论。 128 | 两者都可以被分配给用户,或者组织到 milestones(里程碑) 界面。 129 | 130 | 这个部分主要聚焦于在 GitLab 中与 Git 相关的特性,但是 GitLab 作为一个成熟的系统,它提供了许多其他产品来帮助你协同工作,例如项目 wiki 与系统维护工具。 131 | GitLab 的一个优点在于,服务器设置和运行以后,你将很少需要调整配置文件或通过 SSH 连接服务器;绝大多数的管理和日常使用都可以在浏览器界面中完成。 132 | -------------------------------------------------------------------------------- /04-git-server/sections/gitweb.adoc: -------------------------------------------------------------------------------- 1 | === GitWeb 2 | 3 | (((serving repositories, GitWeb)))(((GitWeb))) 4 | 如果你对项目有读写权限或只读权限,你可能需要建立起一个基于网页的简易查看器。 5 | Git 提供了一个叫做 GitWeb 的 CGI 脚本来做这项工作。 6 | 7 | [[gitweb]] 8 | .GitWeb 的网页用户界面 9 | image::../images/git-instaweb.png[GitWeb 的网页用户界面] 10 | 11 | 如果你想要查看 GitWeb 如何展示你的项目,并且在服务器上安装了轻量级网络服务器比如 `lighttpd` 或 `webrick`, Git 提供了一个命令来让你启动一个临时的服务器。 12 | 在 Linux 系统的电脑上,`lighttpd` 通常已经安装了,所以你只需要在项目目录里执行 `git instaweb` 命令即可。 13 | 如果你使用 Mac 系统, Mac OS X Leopard 系统已经预安装了 Ruby,所以 `webrick` 或许是你最好的选择。 14 | 如果不想使用 lighttpd 启动 `instaweb` 命令,你需要在执行时加入 `--httpd` 参数。(((git commands, instaweb))) 15 | 16 | [source,console] 17 | ---- 18 | $ git instaweb --httpd=webrick 19 | [2009-02-21 10:02:21] INFO WEBrick 1.3.1 20 | [2009-02-21 10:02:21] INFO ruby 1.8.6 (2008-03-03) [universal-darwin9.0] 21 | ---- 22 | 23 | 这个命令启动了一个监听 1234 端口的 HTTP 服务器,并且自动打开了浏览器。 24 | 这对你来说十分方便。 25 | 当你已经完成了工作并想关闭这个服务器,你可以执行同一个命令,并加上 `--stop` 选项: 26 | 27 | [source,console] 28 | ---- 29 | $ git instaweb --httpd=webrick --stop 30 | ---- 31 | 32 | 如果你现在想为你的团队或你托管的开源项目持续的运行这个页面,你需要通过普通的 Web 服务器来设置 CGI 脚本。 33 | 一些 Linux 发行版的软件库有 `gitweb` 包,可以通过 `apt` 或 `yum` 来安装,你可以先试试。 34 | 接下来我们来快速的了解一下如何手动安装 GitWeb。 35 | 首先,你需要获得 Git 的源代码,它包含了 GitWeb ,并可以生成自定义的 CGI 脚本: 36 | 37 | [source,console] 38 | ---- 39 | $ git clone git://git.kernel.org/pub/scm/git/git.git 40 | $ cd git/ 41 | $ make GITWEB_PROJECTROOT="/opt/git" prefix=/usr gitweb 42 | SUBDIR gitweb 43 | SUBDIR ../ 44 | make[2]: `GIT-VERSION-FILE' is up to date. 45 | GEN gitweb.cgi 46 | GEN static/gitweb.js 47 | $ sudo cp -Rf gitweb /var/www/ 48 | ---- 49 | 50 | 需要注意的是,你需要在命令中指定 `GITWEB_PROJECTROOT` 变量来让程序知道你的 Git 版本库的位置。 51 | 现在,你需要在 Apache 中使用这个 CGI 脚本,你需要为此添加一个虚拟主机: 52 | 53 | [source,console] 54 | ---- 55 | 56 | ServerName gitserver 57 | DocumentRoot /var/www/gitweb 58 | 59 | Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch 60 | AllowOverride All 61 | order allow,deny 62 | Allow from all 63 | AddHandler cgi-script cgi 64 | DirectoryIndex gitweb.cgi 65 | 66 | 67 | ---- 68 | 69 | 再次提醒,GitWeb 可以通过任何一个支持 CGI 或 Perl 的网络服务器架设;如果你需要的话,架设起来应该不会很困难。 70 | 现在,你可以访问 `http://gitserver/` 在线查看你的版本库。 71 | -------------------------------------------------------------------------------- /04-git-server/sections/hosted.adoc: -------------------------------------------------------------------------------- 1 | === 第三方托管的选择 2 | 3 | 如果不想设立自己的 Git 服务器,你可以选择将你的 Git 项目托管到一个外部专业的托管网站。 4 | 这带来了一些好处:一个托管网站可以用来快速建立并开始项目,且无需进行服务器维护和监控工作。 5 | 即使你在内部设立并且运行了自己的服务器,你仍然可以把你的开源代码托管在公共托管网站 - 这通常更有助于开源社区来发现和帮助你。 6 | 7 | 现在,有非常多的托管供你选择,每个选择都有不同的优缺点。 8 | 欲查看最新列表,请浏览 Git 维基的 GitHosting 页面 https://git.wiki.kernel.org/index.php/GitHosting[] 9 | 10 | 我们会在 <<_github>> 详细讲解 GitHub,作为目前最大的 Git 托管平台,你很可能需要与托管在 GitHub 上的项目进行交互,而且你也很可能并不想去设立你自己的 Git 服务器。 11 | -------------------------------------------------------------------------------- /04-git-server/sections/setting-up-server.adoc: -------------------------------------------------------------------------------- 1 | [[_setting_up_server]] 2 | === 配置服务器 3 | 4 | 我们来看看如何配置服务器端的 SSH 访问。 5 | 本例中,我们将使用 `authorized_keys` 方法来对用户进行认证。 6 | 同时我们假设你使用的操作系统是标准的 Linux 发行版,比如 Ubuntu。 7 | 首先,创建一个操作系统用户 `git`,并为其建立一个 `.ssh` 目录。 8 | 9 | [source,console] 10 | ---- 11 | $ sudo adduser git 12 | $ su git 13 | $ cd 14 | $ mkdir .ssh && chmod 700 .ssh 15 | $ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys 16 | ---- 17 | 18 | 接着,我们需要为系统用户 `git` 的 `authorized_keys` 文件添加一些开发者 SSH 公钥。 19 | 假设我们已经获得了若干受信任的公钥,并将它们保存在临时文件中。 20 | 与前文类似,这些公钥看起来是这样的: 21 | 22 | [source,console] 23 | ---- 24 | $ cat /tmp/id_rsa.john.pub 25 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4L 26 | ojG6rs6hPB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4k 27 | Yjh6541NYsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9Ez 28 | Sdfd8AcCIicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myiv 29 | O7TCUSBdLQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPq 30 | dAv8JggJICUvax2T9va5 gsg-keypair 31 | ---- 32 | 33 | 将这些公钥加入系统用户 `git` 的 `.ssh` 目录下 `authorized_keys` 文件的末尾: 34 | 35 | [source,console] 36 | ---- 37 | $ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys 38 | $ cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys 39 | $ cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys 40 | ---- 41 | 42 | 现在我们来为开发者新建一个空仓库。可以借助带 `--bare` 选项的 `git init` 命令来做到这一点,该命令在初始化仓库时不会创建工作目录:(((git commands, init, bare))) 43 | 44 | [source,console] 45 | ---- 46 | $ cd /opt/git 47 | $ mkdir project.git 48 | $ cd project.git 49 | $ git init --bare 50 | Initialized empty Git repository in /opt/git/project.git/ 51 | ---- 52 | 53 | 接着,John、Josie 或者 Jessica 中的任意一人可以将他们项目的最初版本推送到这个仓库中,他只需将此仓库设置为项目的远程仓库并向其推送分支。 54 | 请注意,每添加一个新项目,都需要有人登录服务器取得 shell,并创建一个裸仓库。 55 | 我们假定这个设置了 `git` 用户和 Git 仓库的服务器使用 `gitserver` 作为主机名。 56 | 同时,假设该服务器运行在内网,并且你已在 DNS 配置中将 `gitserver` 指向此服务器。那么我们可以运行如下命令(假定 `myproject` 是已有项目且其中已包含文件): 57 | 58 | [source,console] 59 | ---- 60 | # on John's computer 61 | $ cd myproject 62 | $ git init 63 | $ git add . 64 | $ git commit -m 'initial commit' 65 | $ git remote add origin git@gitserver:/opt/git/project.git 66 | $ git push origin master 67 | ---- 68 | 69 | 此时,其他开发者可以克隆此仓库,并推回各自的改动,步骤很简单: 70 | 71 | [source,console] 72 | ---- 73 | $ git clone git@gitserver:/opt/git/project.git 74 | $ cd project 75 | $ vim README 76 | $ git commit -am 'fix for the README file' 77 | $ git push origin master 78 | ---- 79 | 80 | 通过这种方法,你可以快速搭建一个具有读写权限、面向多个开发者的 Git 服务器。 81 | 82 | 需要注意的是,目前所有(获得授权的)开发者用户都能以系统用户 `git` 的身份登录服务器从而获得一个普通 shell。 83 | 如果你想对此加以限制,则需要修改 `passwd` 文件中(`git` 用户所对应)的 shell 值。 84 | 85 | 借助一个名为 `git-shell` 的受限 shell 工具,你可以方便地将用户 `git` 的活动限制在与 Git 相关的范围内。该工具随 Git 软件包一同提供。 86 | 如果将 `git-shell` 设置为用户 `git` 的登录 shell(login shell),那么用户 `git` 便不能获得此服务器的普通 shell 访问权限。 87 | 若要使用 `git-shell`,需要用它替换掉 bash 或 csh,使其成为系统用户的登录 shell。 88 | 为进行上述操作,首先你必须确保 `git-shell` 已存在于 `/etc/shells` 文件中: 89 | 90 | [source,console] 91 | ---- 92 | $ cat /etc/shells # see if `git-shell` is already in there. If not... 93 | $ which git-shell # make sure git-shell is installed on your system. 94 | $ sudo vim /etc/shells # and add the path to git-shell from last command 95 | ---- 96 | 97 | 现在你可以使用 `chsh ` 命令修改任一系统用户的 shell: 98 | 99 | [source,console] 100 | ---- 101 | $ sudo chsh git # and enter the path to git-shell, usually: /usr/bin/git-shell 102 | ---- 103 | 104 | 这样,用户 `git` 就只能利用 SSH 连接对 Git 仓库进行推送和拉取操作,而不能登录机器并取得普通 shell。 105 | 如果试图登录,你会发现尝试被拒绝,像这样: 106 | 107 | [source,console] 108 | ---- 109 | $ ssh git@gitserver 110 | fatal: Interactive git shell is not enabled. 111 | hint: ~/git-shell-commands should exist and have read and execute access. 112 | Connection to gitserver closed. 113 | ---- 114 | 115 | 现在,网络相关的 Git 命令依然能够正常工作,但是开发者用户已经无法得到一个普通 shell 了。 116 | 正如输出信息所提示的,你也可以在 `git` 用户的家目录下建立一个目录,来对 `git-shell` 命令进行一定程度的自定义。 117 | 比如,你可以限制掉某些本应被服务器接受的 Git 命令,或者对刚才的 SSH 拒绝登录信息进行自定义,这样,当有开发者用户以类似方式尝试登录时,便会看到你的信息。 118 | 要了解更多有关自定义 shell 的信息,请运行 `git help shell`。(((git commands, help))) 119 | -------------------------------------------------------------------------------- /04-git-server/sections/smart-http.adoc: -------------------------------------------------------------------------------- 1 | === Smart HTTP 2 | 3 | (((serving repositories, HTTP))) 4 | 我们一般通过 SSH 进行授权访问,通过 git:// 进行无授权访问,但是还有一种协议可以同时实现以上两种方式的访问。 5 | 设置 Smart HTTP 一般只需要在服务器上启用一个 Git 自带的名为 `git-http-backend` 的 CGI 脚本。(((git commands, "http-backend"))) 6 | 该 CGI 脚本将会读取由 `git fetch` 或 `git push` 命令向 HTTP URL 发送的请求路径和头部信息,来判断该客户端是否支持 HTTP 通信(不低于 1.6.6 版本的客户端支持此特性)。 7 | 如果 CGI 发现该客户端支持智能(Smart)模式,它将会以智能模式与它进行通信,否则它将会回落到哑(Dumb)模式下(因此它可以对某些老的客户端实现向下兼容)。 8 | 9 | 在完成以上简单的安装步骤后, 10 | 我们将用 Apache 来作为 CGI 服务器。 11 | 如果你没有安装 Apache,你可以在 Linux 环境下执行如下或类似的命令来安装:(((Apache))) 12 | 13 | [source,console] 14 | ---- 15 | $ sudo apt-get install apache2 apache2-utils 16 | $ a2enmod cgi alias env 17 | ---- 18 | 19 | 该操作将会启用 `mod_cgi`, `mod_alias`, 和 `mod_env` 等 Apache 模块, 这些模块都是使该功能正常工作所必须的。 20 | 21 | 接下来我们要向 Apache 配置文件添加一些内容,来让 `git-http-backend` 作为 Web 服务器对 `/git` 路径请求的处理器。 22 | 23 | [source,console] 24 | ---- 25 | SetEnv GIT_PROJECT_ROOT /opt/git 26 | SetEnv GIT_HTTP_EXPORT_ALL 27 | ScriptAlias /git/ /usr/lib/git-core/git-http-backend/ 28 | ---- 29 | 30 | 如果留空 `GIT_HTTP_EXPORT_ALL` 这个环境变量,Git 将只对无授权客户端提供带 `git-daemon-export-ok` 文件的版本库,就像 Git 守护进程一样。 31 | 32 | 接着你需要让 Apache 接受通过该路径的请求,添加如下的内容至 Apache 配置文件: 33 | 34 | [source,console] 35 | ---- 36 | 37 | Options ExecCGI Indexes 38 | Order allow,deny 39 | Allow from all 40 | Require all granted 41 | 42 | ---- 43 | 44 | 最后,如果想实现写操作授权验证,使用如下的未授权屏蔽配置即可: 45 | 46 | [source,console] 47 | ---- 48 | 49 | AuthType Basic 50 | AuthName "Git Access" 51 | AuthUserFile /opt/git/.htpasswd 52 | Require valid-user 53 | 54 | ---- 55 | 56 | 这需要你创建一个包含所有合法用户密码的 `.htaccess` 文件。 57 | 以下是一个添加 ``schacon'' 用户到此文件的例子: 58 | 59 | [source,console] 60 | ---- 61 | $ htdigest -c /opt/git/.htpasswd "Git Access" schacon 62 | ---- 63 | 64 | 你可以通过许多方式添加 Apache 授权用户,选择使用其中一种方式即可。 65 | 以上仅仅只是我们可以找到的最简单的一个例子。 66 | 如果愿意的话,你也可以通过 SSL 运行它,以保证所有数据是在加密状态下进行传输的。 67 | 68 | 我们不想深入去讲解 Apache 配置文件,因为你可能会使用不同的 Web 服务器,或者可能有不同的授权需求。 69 | 它的主要原理是使用一个 Git 附带的,名为 `git-http-backend` 的 CGI。它被引用来处理协商通过 HTTP 发送和接收的数据。 70 | 它本身并不包含任何授权功能,但是授权功能可以在 Web 服务器层引用它时被轻松实现。 71 | 你可以在任何所有可以处理 CGI 的 Web 服务器上办到这点,所以随便挑一个你最熟悉的 Web 服务器试手吧。 72 | 73 | [NOTE] 74 | ==== 75 | 欲了解更多的有关配置 Apache 授权访问的信息,请通过以下链接浏览 Apache 文档: http://httpd.apache.org/docs/current/howto/auth.html[] 76 | ==== 77 | -------------------------------------------------------------------------------- /04-git-server/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 你有多种远程存取 Git 仓库的选择便于与其他人合作或是分享你的工作。 4 | 5 | 运行你自己的服务器将有许多权限且允许你运行该服务于你自己的防火墙内,但如此通常需要耗费你大量的时间去设置与维护服务器。 6 | 如果你放置你的资料于托管服务器内,可轻易的设置与维护;无论如何,你必须能够保存你的代码在其他服务器,且某些组织不允许此作法。 7 | 这将直接了当的决定哪个作法或组合的方式较适合你或你的组织。 8 | -------------------------------------------------------------------------------- /05-distributed-git/1-distributed-git.adoc: -------------------------------------------------------------------------------- 1 | [[_distributed_git]] 2 | == 分布式 Git 3 | 4 | (((distributed git))) 5 | 你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令。你现在可以学习如何利用 Git 提供的一些分布式工作流程了。 6 | 7 | 这一章中,你将会学习如何作为贡献者或整合者,在一个分布式协作的环境中使用 Git。 8 | 你会学习为一个项目成功地贡献代码,并接触一些最佳实践方式,让你和项目的维护者能轻松地完成这个过程。另外,你也会学到如何管理有很多开发者提交贡献的项目。 9 | -------------------------------------------------------------------------------- /05-distributed-git/images/benevolent-dictator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/benevolent-dictator.png -------------------------------------------------------------------------------- /05-distributed-git/images/centralized_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/centralized_workflow.png -------------------------------------------------------------------------------- /05-distributed-git/images/git-diff-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/git-diff-check.png -------------------------------------------------------------------------------- /05-distributed-git/images/integration-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/integration-manager.png -------------------------------------------------------------------------------- /05-distributed-git/images/large-merges-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/large-merges-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/large-merges-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/large-merges-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/managed-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/managed-team-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/managed-team-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/managed-team-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/managed-team-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/managed-team-3.png -------------------------------------------------------------------------------- /05-distributed-git/images/managed-team-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/managed-team-flow.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-3.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-4 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-4 2.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-4.png -------------------------------------------------------------------------------- /05-distributed-git/images/merging-workflows-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/merging-workflows-5.png -------------------------------------------------------------------------------- /05-distributed-git/images/public-small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/public-small-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/public-small-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/public-small-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/public-small-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/public-small-3.png -------------------------------------------------------------------------------- /05-distributed-git/images/rebasing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/rebasing-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/rebasing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/rebasing-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-1.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-2.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-3.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-4.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-5.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-6.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-7.png -------------------------------------------------------------------------------- /05-distributed-git/images/small-team-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/05-distributed-git/images/small-team-flow.png -------------------------------------------------------------------------------- /05-distributed-git/sections/distributed-workflows.adoc: -------------------------------------------------------------------------------- 1 | === 分布式工作流程 2 | 3 | (((workflows))) 4 | 同传统的集中式版本控制系统(CVCS)不同,Git 的分布式特性使得开发者间的协作变得更加灵活多样。 5 | 在集中式系统中,每个开发者就像是连接在集线器上的节点,彼此的工作方式大体相像。 6 | 而在 Git 中,每个开发者同时扮演着节点和集线器的角色——也就是说,每个开发者既可以将自己的代码贡献到其他的仓库中,同时也能维护自己的公开仓库,让其他人可以在其基础上工作并贡献代码。 7 | 由此,Git 的分布式协作可以为你的项目和团队衍生出种种不同的工作流程,接下来的章节会介绍几种利用了 Git 的这种灵活性的常见应用方式。 8 | 我们将讨论每种方式的优点以及可能的缺点;你可以选择使用其中的某一种,或者将它们的特性混合搭配使用。 9 | 10 | ==== 集中式工作流 11 | 12 | (((workflows, centralized))) 13 | 集中式系统中通常使用的是单点协作模型——集中式工作流。 14 | 一个中心集线器,或者说仓库,可以接受代码,所有人将自己的工作与之同步。 15 | 若干个开发者则作为节点——也就是中心仓库的消费者——并且与其进行同步。 16 | 17 | .集中式工作流。 18 | image::../images/centralized_workflow.png[集中式工作流。] 19 | 20 | 这意味着如果两个开发者从中心仓库克隆代码下来,同时作了一些修改,那么只有第一个开发者可以顺利地把数据推送回共享服务器。 21 | 第二个开发者在推送修改之前,必须先将第一个人的工作合并进来,这样才不会覆盖第一个人的修改。 22 | 这和 Subversion(((Subversion))) (或任何 CVCS)中的概念一样,而且这个模式也可以很好地运用到 Git 中。 23 | 24 | 如果在公司或者团队中,你已经习惯了使用这种集中式工作流程,完全可以继续采用这种简单的模式。 25 | 只需要搭建好一个中心仓库,并给开发团队中的每个人推送数据的权限,就可以开展工作了。Git 不会让用户覆盖彼此的修改。 26 | 例如 John 和 Jessica 同时开始工作。 27 | John 完成了他的修改并推送到服务器。 28 | 接着 Jessica 尝试提交她自己的修改,却遭到服务器拒绝。 29 | 她被告知她的修改正通过非快进式(non-fast-forward)的方式推送,只有将数据抓取下来并且合并后方能推送。 30 | 这种模式的工作流程的使用非常广泛,因为大多数人对其很熟悉也很习惯。 31 | 32 | 当然这并不局限于小团队。 33 | 利用 Git 的分支模型,通过同时在多个分支上工作的方式,即使是上百人的开发团队也可以很好地在单个项目上协作。 34 | 35 | [[_integration_manager]] 36 | ==== 集成管理者工作流 37 | 38 | (((workflows, integration manager))) 39 | Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。 40 | 这种情形下通常会有个代表``官方''项目的权威的仓库。 41 | 要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。 42 | 接着你可以请求官方仓库的维护者拉取更新合并到主项目。 43 | 维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。 44 | 这一流程的工作方式如下所示(见 <>): 45 | 46 | 1. 项目维护者推送到主仓库。 47 | 2. 贡献者克隆此仓库,做出修改。 48 | 3. 贡献者将数据推送到自己的公开仓库。 49 | 4. 贡献者给维护者发送邮件,请求拉取自己的更新。 50 | 5. 维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改。 51 | 6. 维护者将合并后的修改推送到主仓库。 52 | 53 | [[wfdiag_b]] 54 | .集成管理者工作流。 55 | image::../images/integration-manager.png[集成管理者工作流。] 56 | 57 | (((forking))) 58 | 这是 GitHub 和 GitLab 等集线器式(hub-based)工具最常用的工作流程。人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。 59 | 这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。 60 | 贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己节奏工作。 61 | 62 | ==== 司令官与副官工作流 63 | 64 | (((workflows, dictator and lieutenants))) 65 | 这其实是多仓库工作流程的变种。 66 | 一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 67 | 被称为副官(lieutenant)的各个集成管理者分别负责集成项目中的特定部分。 68 | 所有这些副官头上还有一位称为司令官(dictator)的总集成管理者负责统筹。 69 | 司令官维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。 70 | 整个流程看起来是这样的(见 <>): 71 | 72 | 1. 普通开发者在自己的特性分支上工作,并根据 `master` 分支进行变基。 73 | 这里是司令官的`master`分支。 74 | 2. 副官将普通开发者的特性分支合并到自己的 `master` 分支中。 75 | 3. 司令官将所有副官的 `master` 分支并入自己的 `master` 分支中。 76 | 4. 司令官将集成后的 `master` 分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基。 77 | 78 | [[wfdiag_c]] 79 | .司令官与副官工作流。 80 | image::../images/benevolent-dictator.png[司令官与副官工作流。] 81 | 82 | 这种工作流程并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。 83 | 利用这种方式,项目总负责人(即司令官)可以把大量分散的集成工作委托给不同的小组负责人分别处理,然后在不同时刻将大块的代码子集统筹起来,用于之后的整合。 84 | 85 | ==== 工作流程总结 86 | 87 | 上面介绍了在 Git 等分布式系统中经常使用的工作流程,但是在实际的开发中,你会遇到许多可能适合你的特定工作流程的变种。 88 | 现在你应该已经清楚哪种工作流程组合可能比较适合你了,我们会给出一些如何扮演不同工作流程中主要角色的更具体的例子。 89 | 下一节我们将会学习为项目做贡献的一些常用模式。 90 | -------------------------------------------------------------------------------- /05-distributed-git/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | 2 | === 总结 3 | 4 | 你现在能自如地使用 Git 为项目做出贡献、维护自己的项目或采纳其他用户的贡献了。 5 | 恭喜你成为了一个高效的 Git 开发者! 6 | 下一章中,你将会学到如何使用规模最大最流行的 Git 托管服务,GitHub。 7 | -------------------------------------------------------------------------------- /06-github/1-github.adoc: -------------------------------------------------------------------------------- 1 | [[_github]] 2 | == GitHub 3 | 4 | (((GitHub))) 5 | GitHub 是最大的 Git 版本库托管商,是成千上万的开发者和项目能够合作进行的中心。 6 | 大部分 Git 版本库都托管在 GitHub,很多开源项目使用 GitHub 实现 Git 托管、问题追踪、代码审查以及其它事情。 7 | 所以,尽管这不是 Git 开源项目的直接部分,但如果想要专业地使用 Git,你将不可避免地与 GitHub 打交道,所以这依然是一个绝好的学习机会。 8 | 9 | 本章将讨论如何高效地使用 GitHub。 10 | 我们将学习如何注册和管理账户、创建和使用 Git 版本库、向已有项目贡献的通用流程以及如何接受别人向你自己项目的贡献、GitHub 的编程接口和很多能够让这些操作更简单的小提示。 11 | 12 | 如果你对如何使用 GitHub 托管自己的项目,或者与已经托管在 GitHub 上面的项目进行合作没有兴趣,可以直接跳到 <<_git_tools>> 这一章。 13 | 14 | [WARNING] 15 | .接口的改变 16 | ==== 17 | 需要注意一点,同很多活跃的网站一样,书中截取的界面会随时间而改变。 18 | 希望我们试图表达的核心思想一直是不变的,但是,如果你想要这些截图的更新版本,本书的在线版本或许有更新的截图。 19 | ==== 20 | -------------------------------------------------------------------------------- /06-github/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/1.pdf -------------------------------------------------------------------------------- /06-github/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/1.png -------------------------------------------------------------------------------- /06-github/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/10.pdf -------------------------------------------------------------------------------- /06-github/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/10.png -------------------------------------------------------------------------------- /06-github/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/2.pdf -------------------------------------------------------------------------------- /06-github/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/2.png -------------------------------------------------------------------------------- /06-github/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/3.pdf -------------------------------------------------------------------------------- /06-github/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/3.png -------------------------------------------------------------------------------- /06-github/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/4.pdf -------------------------------------------------------------------------------- /06-github/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/4.png -------------------------------------------------------------------------------- /06-github/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/5.pdf -------------------------------------------------------------------------------- /06-github/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/5.png -------------------------------------------------------------------------------- /06-github/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/6.pdf -------------------------------------------------------------------------------- /06-github/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/6.png -------------------------------------------------------------------------------- /06-github/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/7.pdf -------------------------------------------------------------------------------- /06-github/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/7.png -------------------------------------------------------------------------------- /06-github/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/8.pdf -------------------------------------------------------------------------------- /06-github/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/8.png -------------------------------------------------------------------------------- /06-github/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/9.pdf -------------------------------------------------------------------------------- /06-github/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/callouts/9.png -------------------------------------------------------------------------------- /06-github/images/2fa-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/2fa-1.png -------------------------------------------------------------------------------- /06-github/images/account-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/account-settings.png -------------------------------------------------------------------------------- /06-github/images/avatar-crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/avatar-crop.png -------------------------------------------------------------------------------- /06-github/images/blink-01-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-01-start.png -------------------------------------------------------------------------------- /06-github/images/blink-02-pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-02-pr.png -------------------------------------------------------------------------------- /06-github/images/blink-03-pull-request-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-03-pull-request-open.png -------------------------------------------------------------------------------- /06-github/images/blink-04-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-04-email.png -------------------------------------------------------------------------------- /06-github/images/blink-04-pr-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-04-pr-comment.png -------------------------------------------------------------------------------- /06-github/images/blink-05-general-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-05-general-comment.png -------------------------------------------------------------------------------- /06-github/images/blink-06-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-06-final.png -------------------------------------------------------------------------------- /06-github/images/blink-pull-request-open copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-pull-request-open copy.png -------------------------------------------------------------------------------- /06-github/images/blink-pull-request-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/blink-pull-request-open.png -------------------------------------------------------------------------------- /06-github/images/collaborators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/collaborators.png -------------------------------------------------------------------------------- /06-github/images/email-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/email-settings.png -------------------------------------------------------------------------------- /06-github/images/emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/emoji.png -------------------------------------------------------------------------------- /06-github/images/forkbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/forkbutton.png -------------------------------------------------------------------------------- /06-github/images/hubot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/hubot.png -------------------------------------------------------------------------------- /06-github/images/maint-01-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-01-email.png -------------------------------------------------------------------------------- /06-github/images/maint-02-merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-02-merge.png -------------------------------------------------------------------------------- /06-github/images/maint-03-email-resp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-03-email-resp.png -------------------------------------------------------------------------------- /06-github/images/maint-04-target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-04-target.png -------------------------------------------------------------------------------- /06-github/images/maint-05-mentions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-05-mentions.png -------------------------------------------------------------------------------- /06-github/images/maint-06-unsubscribe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-06-unsubscribe.png -------------------------------------------------------------------------------- /06-github/images/maint-07-notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-07-notifications.png -------------------------------------------------------------------------------- /06-github/images/maint-08-notifications-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-08-notifications-page.png -------------------------------------------------------------------------------- /06-github/images/maint-09-contrib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-09-contrib.png -------------------------------------------------------------------------------- /06-github/images/maint-10-default-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-10-default-branch.png -------------------------------------------------------------------------------- /06-github/images/maint-11-transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/maint-11-transfer.png -------------------------------------------------------------------------------- /06-github/images/markdown-01-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-01-example.png -------------------------------------------------------------------------------- /06-github/images/markdown-02-tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-02-tasks.png -------------------------------------------------------------------------------- /06-github/images/markdown-03-task-summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-03-task-summary.png -------------------------------------------------------------------------------- /06-github/images/markdown-04-fenced-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-04-fenced-code.png -------------------------------------------------------------------------------- /06-github/images/markdown-05-quote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-05-quote.png -------------------------------------------------------------------------------- /06-github/images/markdown-06-emoji-complete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-06-emoji-complete.png -------------------------------------------------------------------------------- /06-github/images/markdown-07-emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-07-emoji.png -------------------------------------------------------------------------------- /06-github/images/markdown-08-drag-drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/markdown-08-drag-drop.png -------------------------------------------------------------------------------- /06-github/images/mentions-01-syntax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/mentions-01-syntax.png -------------------------------------------------------------------------------- /06-github/images/mentions-02-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/mentions-02-render.png -------------------------------------------------------------------------------- /06-github/images/mentions-03-closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/mentions-03-closed.png -------------------------------------------------------------------------------- /06-github/images/new-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/new-repo.png -------------------------------------------------------------------------------- /06-github/images/neworg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/neworg.png -------------------------------------------------------------------------------- /06-github/images/newrepo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/newrepo.png -------------------------------------------------------------------------------- /06-github/images/newrepoform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/newrepoform.png -------------------------------------------------------------------------------- /06-github/images/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/notifications.png -------------------------------------------------------------------------------- /06-github/images/orgs-01-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/orgs-01-page.png -------------------------------------------------------------------------------- /06-github/images/orgs-02-teams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/orgs-02-teams.png -------------------------------------------------------------------------------- /06-github/images/orgs-03-audit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/orgs-03-audit.png -------------------------------------------------------------------------------- /06-github/images/pr-01-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/pr-01-fail.png -------------------------------------------------------------------------------- /06-github/images/pr-02-merge-fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/pr-02-merge-fix.png -------------------------------------------------------------------------------- /06-github/images/reposettingslink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/reposettingslink.png -------------------------------------------------------------------------------- /06-github/images/scripting-01-services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-01-services.png -------------------------------------------------------------------------------- /06-github/images/scripting-02-email-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-02-email-service.png -------------------------------------------------------------------------------- /06-github/images/scripting-03-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-03-webhook.png -------------------------------------------------------------------------------- /06-github/images/scripting-04-webhook-debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-04-webhook-debug.png -------------------------------------------------------------------------------- /06-github/images/scripting-05-access-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-05-access-token.png -------------------------------------------------------------------------------- /06-github/images/scripting-06-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-06-comment.png -------------------------------------------------------------------------------- /06-github/images/scripting-07-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/scripting-07-status.png -------------------------------------------------------------------------------- /06-github/images/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/signup.png -------------------------------------------------------------------------------- /06-github/images/ssh-keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/ssh-keys.png -------------------------------------------------------------------------------- /06-github/images/your-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/06-github/images/your-profile.png -------------------------------------------------------------------------------- /06-github/sections/1-setting-up-account.adoc: -------------------------------------------------------------------------------- 1 | === 账户的创建和配置 2 | 3 | (((GitHub, user accounts))) 4 | 你所需要做的第一件事是创建一个免费账户。 5 | 直接访问 https://github.com[],选择一个未被占用的用户名,提供一个电子邮件地址和密码,点击写着``Sign up for GitHub''的绿色大按钮即可。 6 | 7 | .GitHub 注册表单。 8 | image::../images/signup.png[GitHub 注册表单。] 9 | 10 | 你将看到的下一个页面是升级计划的价格页面,目前我们可以直接忽略这个页面。 11 | GitHub 会给你提供的邮件地址发送一封验证邮件。 12 | 尽快到你的邮箱进行验证,这是非常重要的(我们会在后面了解到这点)。 13 | 14 | [NOTE] 15 | ==== 16 | GitHub 为免费账户提供了完整功能,限制是你的项目都将被完全公开(每个人都具有读权限)。 17 | GitHub 的付费计划可以让你拥有一定数目的私有项目,不过本书将不涉及这部分内容。 18 | ==== 19 | 20 | 点击屏幕左上角的 Octocat 图标,你将来到控制面板页面。 21 | 现在,你已经做好了使用 GitHub 的准备工作。 22 | 23 | ==== SSH 访问 24 | 25 | (((SSH keys, with GitHub))) 26 | 现在,你完全可以使用 `https://` 协议,通过你刚刚创建的用户名和密码访问 Git 版本库。 27 | 但是,如果仅仅克隆公有项目,你甚至不需要注册——刚刚我们创建的账户是为了以后 fork 其它项目,以及推送我们自己的修改。 28 | 29 | 如果你习惯使用 SSH 远程,你需要配置一个公钥。 30 | (如果你没有公钥,参考 <<_generate_ssh_key>>。) 31 | 使用窗口右上角的链接打开你的账户设置: 32 | 33 | .``Account settings''链接。 34 | image::../images/account-settings.png[``Account settings''链接。] 35 | 36 | 然后在左侧选择``SSH keys''部分。 37 | 38 | .``SSH keys''链接。 39 | image::../images/ssh-keys.png[``SSH keys''链接。] 40 | 41 | 在这个页面点击“`Add an SSH key`”按钮,给你的公钥起一个名字,将你的`~/.ssh/id_rsa.pub`(或者自定义的其它名字)公钥文件的内容粘贴到文本区,然后点击``Add key''。 42 | 43 | [NOTE] 44 | ==== 45 | 确保给你的 SSH 密钥起一个能够记得住的名字。 46 | 你可以为每一个密钥起名字(例如,“我的笔记本电脑”或者“工作账户”等),以便以后需要吊销密钥时能够方便地区分。 47 | ==== 48 | 49 | [[_personal_avatar]] 50 | ==== 头像 51 | 52 | 下一步,如果愿意的话,你可以将生成的头像换成你喜欢的图片。 53 | 首先,来到``Profile''标签页(在``SSH Keys''标签页上方),点击``Upload new picture''。 54 | 55 | .``Profile''链接。 56 | image::../images/your-profile.png[``Profile''链接。] 57 | 58 | 我们选择了本地磁盘上的一个 Git 图标,上传之后还可以对其进行裁剪。 59 | 60 | .裁剪头像 61 | image::../images/avatar-crop.png[裁剪已上传的头像。] 62 | 63 | 现在,在网站任意有你参与的位置,人们都可以在你的用户名旁边看到你的头像。 64 | 65 | 如果你已经把头像上传到了流行的 Gravatar 托管服务(Wordpress 账户经常使用),默认就会使用这个头像,因此,你就不需要进行这一步骤了。 66 | 67 | ==== 邮件地址 68 | 69 | GitHub 使用用户邮件地址区分 Git 提交。 70 | 如果你在自己的提交中使用了多个邮件地址,希望 GitHub 可以正确地将它们连接起来,你需要在管理页面的 Emails 部分添加你拥有的所有邮箱地址。 71 | 72 | [[_add_email_addresses]] 73 | .添加邮件地址 74 | image::../images/email-settings.png[添加所有邮件地址。] 75 | 76 | 在 <<_add_email_addresses>> 中我们可以看到一些不同的状态。 77 | 顶部的地址是通过验证的,并且被设置为主要地址,这意味着该地址会接收到所有的通知和回复。 78 | 第二个地址是通过验证的,如果愿意的话,可以将其设置为主要地址。 79 | 最后一个地址是未通过验证的,这意味着你不能将其设置为主要地址。 80 | 当 GitHub 发现任意版本库中的任意提交信息包含了这些地址,它就会将其链接到你的账户。 81 | 82 | ==== 两步验证 83 | 84 | 最后,为了额外的安全性,你绝对应当设置两步验证,简写为 ``2FA''。 85 | 两步验证是一种用于降低因你的密码被盗而带来的账户风险的验证机制,现在已经变得越来越流行。 86 | 开启两步验证,GitHub 会要求你用两种不同的验证方法,这样,即使其中一个被攻破,攻击者也不能访问你的账户。 87 | 88 | 你可以在 Account settings 页面的 Security 标签页中找到 Two-factor Authentication 设置。 89 | 90 | .Security 标签页中的 2FA 91 | image::../images/2fa-1.png[Security 标签页中的 2FA] 92 | 93 | 点击``Set up two-factor authentication''按钮,会跳转到设置页面。该页面允许你选择是要在登录时使用手机 app 生成辅助码(一种``基于时间的一次性密码''),还是要 GitHub 通过 SMS 发送辅助码。 94 | 95 | 选择合适的方法后,按照提示步骤设置 2FA,你的账户会变得更安全,每次登录 GitHub 时都需要提供除密码以外的辅助码。 96 | -------------------------------------------------------------------------------- /06-github/sections/4-managing-organization.adoc: -------------------------------------------------------------------------------- 1 | [[_github_orgs]] 2 | === 管理组织 3 | 4 | (((GitHub, organizations))) 5 | 除了个人帐户之外,GitHub 还提供被称为组织(Organizations)的帐户。 6 | 组织账户和个人账户一样都有一个用于存放所拥有项目的命名空间,但是许多其他的东西都是不同的。 7 | 组织帐户代表了一组共同拥有多个项目的人,同时也提供一些工具用于对成员进行分组管理。 8 | 通常,这种账户被用于开源群组(例如:“perl”或者“rails”),或者公司(例如:“google”或者“twitter”)。 9 | 10 | ==== 组织的基本知识 11 | 12 | 我们可以很简单地创建一个组织,只需要点击任意 GitHub 页面右上角的“+”图标,在菜单中选择“New organization”即可。 13 | 14 | .``New organization''菜单项 15 | image::../images/neworg.png[``New organization''菜单项] 16 | 17 | 首先你必须提供组织的名称和组织的主要联系邮箱。 18 | 然后,如果你希望的话,也可以邀请其他用户作为共同拥有人。 19 | 20 | 完成以上步骤后,你就会拥有一个全新的组织。 21 | 类似于个人帐户,如果组织的所有内容都是开源的,那么你就可以免费使用这个组织。 22 | 23 | 作为一个组织的拥有者,当你在派生一个版本库的时候,你可以选择把它派生到你的组织的命名空间内。 24 | 当你新建版本库时,你可以把它存放到你的个人帐户或你拥有的组织内。 25 | 同时,你也会自动地“关注”所有这些组织内的新版本库。 26 | 27 | 就像<<_personal_avatar>>,你可以为你的组织上传头像,使它更个性化。 28 | 同时,也和个人帐户类似,组织会有一个着陆页(landing page),用于列出该组织所有的版本库,并且该页面可供所有人浏览。 29 | 30 | 下面我们来说一些组织和个人帐户不同的地方。 31 | 32 | ==== 团队 33 | 34 | 组织使用团队(Teams)来管理成员,团队就是组织中的一组个人账户和版本库,以及团队成员对这些版本库的访问权限。 35 | 36 | 例如,假设你的公司有三个版本库:`frontend`、`backend` 和 `deployscripts`。 37 | 你会希望你的 HTML/CSS/Javascript 开发者有 `frontend` 或者 `backend` 的访问权限,操作人员有 `backend` 和 `deployscripts` 的访问权限。 38 | 团队让这个任务变得更简单,而不用为每个版本库管理它的协作者。 39 | 40 | 组织页面主要由一个面板(dashboard)构成,这个仪表盘包含了这个组织内的所有版本库,用户和团队。 41 | 42 | [[_org_page]] 43 | .组织页面 44 | image::../images/orgs-01-page.png[组织页面] 45 | 46 | 你可以点击 <<_org_page>> 右边的团队侧边栏(Teams)来管理你的团队。 47 | 点击之后,你会进入一个新页面,在这里你可以添加新成员和版本库到团队中,或者管理团队的访问权限和其它设置。 48 | 每个团队对于版本库可以有只读、读写和管理三种权限。 49 | 你可以通过点击在 <<_team_page>> 内的 “Settings” 按钮更改相应权限等级。 50 | 51 | [[_team_page]] 52 | .团队页面 53 | image::../images/orgs-02-teams.png[团队页面] 54 | 55 | 当你邀请一个用户加入团队,该用户会收到一封通知他被邀请的邮件。 56 | 57 | 除此之外,团队也类似于个人帐户,有 `@mentions`(例如:`@acmecorp/frontend`)的功能,不同之处就在于被提及的团队内*所有*成员都会成为这个话题的订阅者。 58 | 当你希望得到团队中某个人的关注,又不知道具体应该问谁的时候,这个功能就显得很有帮助。 59 | 60 | 一个用户可以加入任意数量的团队,所以别把自己局限于拥有访问控制的团队。 61 | 对于某一类课题,像 `ux`, `css` 或者 `refactoring` 这样有着特殊关注点的团队就显得很有帮助,而像 `legal` 和 `colorblind` 这样的就完全是针对它们各自领域的。 62 | 63 | ==== 审计日志 64 | 65 | 组织的拥有者还可以访问组织中发生的事情的所有信息。 66 | 在 'Audit Log' 标签页有整个组织的日志,你可以看到谁在世界上哪个地方做了什么事。 67 | 68 | [[_audit_log]] 69 | .审计日志 70 | image::../images/orgs-03-audit.png[] 71 | 72 | 你也可以通过选定某一类型的事件、某个地方、某个人对日志进行过滤。 73 | -------------------------------------------------------------------------------- /06-github/sections/6-summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 现在你已经是一名 GitHub 用户了。 4 | 你知道了如何创建账户、管理组织、创建和推送版本库、向别人的项目提供贡献以及接受别人的贡献。 5 | 在下一章中,你将学习更多强有力的工具,以及处理复杂情况的知识,这些将使你成为真正的 Git 大师。 6 | -------------------------------------------------------------------------------- /07-git-tools/1-git-tools.adoc: -------------------------------------------------------------------------------- 1 | [[_git_tools]] 2 | == Git 工具 3 | 4 | 现在,你已经学习了管理或者维护 Git 仓库、实现代码控制所需的大多数日常命令和工作流程。 5 | 你已经尝试了跟踪和提交文件的基本操作,并且发挥了暂存区和轻量级的分支及合并的威力。 6 | 7 | 接下来你将学习一些 Git 的强大功能,这些功能你可能并不会在日常操作中使用,但在某些时候你可能会需要。 8 | -------------------------------------------------------------------------------- /07-git-tools/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/1.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/1.png -------------------------------------------------------------------------------- /07-git-tools/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/10.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/10.png -------------------------------------------------------------------------------- /07-git-tools/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/2.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/2.png -------------------------------------------------------------------------------- /07-git-tools/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/3.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/3.png -------------------------------------------------------------------------------- /07-git-tools/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/4.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/4.png -------------------------------------------------------------------------------- /07-git-tools/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/5.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/5.png -------------------------------------------------------------------------------- /07-git-tools/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/6.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/6.png -------------------------------------------------------------------------------- /07-git-tools/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/7.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/7.png -------------------------------------------------------------------------------- /07-git-tools/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/8.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/8.png -------------------------------------------------------------------------------- /07-git-tools/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/9.pdf -------------------------------------------------------------------------------- /07-git-tools/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/callouts/9.png -------------------------------------------------------------------------------- /07-git-tools/git-credential-read-only: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'optparse' 4 | 5 | path = File.expand_path '~/.git-credentials' # <1> 6 | OptionParser.new do |opts| 7 | opts.banner = 'USAGE: git-credential-read-only [options] ' 8 | opts.on('-f', '--file PATH', 'Specify path for backing store') do |argpath| 9 | path = File.expand_path argpath 10 | end 11 | end.parse! 12 | 13 | exit(0) unless ARGV[0].downcase == 'get' # <2> 14 | exit(0) unless File.exists? path 15 | 16 | known = {} # <3> 17 | while line = STDIN.gets 18 | break if line.strip == '' 19 | k,v = line.strip.split '=', 2 20 | known[k] = v 21 | end 22 | 23 | File.readlines(path).each do |fileline| # <4> 24 | prot,user,pass,host = fileline.scan(/^(.*?):\/\/(.*?):(.*?)@(.*)$/).first 25 | if prot == known['protocol'] and host == known['host'] then 26 | puts "protocol=#{prot}" 27 | puts "host=#{host}" 28 | puts "username=#{user}" 29 | puts "password=#{pass}" 30 | exit(0) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /07-git-tools/images/double-dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/double-dot.png -------------------------------------------------------------------------------- /07-git-tools/images/replace1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/replace1.png -------------------------------------------------------------------------------- /07-git-tools/images/replace2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/replace2.png -------------------------------------------------------------------------------- /07-git-tools/images/replace3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/replace3.png -------------------------------------------------------------------------------- /07-git-tools/images/replace4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/replace4.png -------------------------------------------------------------------------------- /07-git-tools/images/replace5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/replace5.png -------------------------------------------------------------------------------- /07-git-tools/images/rerere1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/rerere1.png -------------------------------------------------------------------------------- /07-git-tools/images/rerere2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/rerere2.png -------------------------------------------------------------------------------- /07-git-tools/images/rerere3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/rerere3.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-checkout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-checkout.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex1.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex2.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex3.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex4.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex5.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-ex6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-ex6.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-hard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-hard.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-mixed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-mixed.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-path1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-path1.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-path2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-path2.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-path3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-path3.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-soft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-soft.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-squash-r1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-squash-r1.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-squash-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-squash-r2.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-squash-r3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-squash-r3.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-start.png -------------------------------------------------------------------------------- /07-git-tools/images/reset-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/reset-workflow.png -------------------------------------------------------------------------------- /07-git-tools/images/undomerge-reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/undomerge-reset.png -------------------------------------------------------------------------------- /07-git-tools/images/undomerge-revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/undomerge-revert.png -------------------------------------------------------------------------------- /07-git-tools/images/undomerge-revert2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/undomerge-revert2.png -------------------------------------------------------------------------------- /07-git-tools/images/undomerge-revert3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/undomerge-revert3.png -------------------------------------------------------------------------------- /07-git-tools/images/undomerge-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/07-git-tools/images/undomerge-start.png -------------------------------------------------------------------------------- /07-git-tools/sections/bundling.adoc: -------------------------------------------------------------------------------- 1 | [[_bundling]] 2 | === 打包 3 | 4 | 虽然我们已经了解了网络传输 Git 数据的常用方法(如 HTTP,SSH 等),但还有另外一种不太常见却又十分有用的方式。 5 | 6 | Git 可以将它的数据 ``打包'' 到一个文件中。 7 | 这在许多场景中都很有用。 8 | 有可能你的网络中断了,但你又希望将你的提交传给你的合作者们。 9 | 可能你不在办公网中并且出于安全考虑没有给你接入内网的权限。 10 | 可能你的无线、有线网卡坏掉了。 11 | 可能你现在没有共享服务器的权限,你又希望通过邮件将更新发送给别人,却不希望通过 `format-patch` 的方式传输 40 个提交。 12 | 13 | 这些情况下 `git bundle` 就会很有用。 14 | `bundle` 命令会将 `git push` 命令所传输的所有内容打包成一个二进制文件,你可以将这个文件通过邮件或者闪存传给其他人,然后解包到其他的仓库中。 15 | 16 | 来看看一个简单的例子。 17 | 假设你有一个包含两个提交的仓库: 18 | 19 | [source,console] 20 | ---- 21 | $ git log 22 | commit 9a466c572fe88b195efd356c3f2bbeccdb504102 23 | Author: Scott Chacon 24 | Date: Wed Mar 10 07:34:10 2010 -0800 25 | 26 | second commit 27 | 28 | commit b1ec3248f39900d2a406049d762aa68e9641be25 29 | Author: Scott Chacon 30 | Date: Wed Mar 10 07:34:01 2010 -0800 31 | 32 | first commit 33 | ---- 34 | 35 | 如果你想把这个仓库发送给其他人但你没有其他仓库的权限,或者就是懒得新建一个仓库,你就可以用 `git bundle create` 命令来打包。 36 | 37 | [source,console] 38 | ---- 39 | $ git bundle create repo.bundle HEAD master 40 | Counting objects: 6, done. 41 | Delta compression using up to 2 threads. 42 | Compressing objects: 100% (2/2), done. 43 | Writing objects: 100% (6/6), 441 bytes, done. 44 | Total 6 (delta 0), reused 0 (delta 0) 45 | ---- 46 | 47 | 然后你就会有一个名为 `repo.bundle` 的文件,该文件包含了所有重建该仓库 `master` 分支所需的数据。 48 | 在使用 `bundle` 命令时,你需要列出所有你希望打包的引用或者提交的区间。 49 | 如果你希望这个仓库可以在别处被克隆,你应该像例子中那样增加一个 HEAD 引用。 50 | 51 | 你可以将这个 `repo.bundle` 文件通过邮件或者U盘传给别人。 52 | 53 | 另一方面,假设别人传给你一个 `repo.bundle` 文件并希望你在这个项目上工作。 54 | 你可以从这个二进制文件中克隆出一个目录,就像从一个 URL 克隆一样。 55 | 56 | [source,console] 57 | ---- 58 | $ git clone repo.bundle repo 59 | Initialized empty Git repository in /private/tmp/bundle/repo/.git/ 60 | $ cd repo 61 | $ git log --oneline 62 | 9a466c5 second commit 63 | b1ec324 first commit 64 | ---- 65 | 66 | 如果你在打包时没有包含 HEAD 引用,你还需要在命令后指定一个 `-b master` 或者其他被引入的分支,否则 Git 不知道应该检出哪一个分支。 67 | 68 | 现在假设你提交了 3 个修订,并且要用邮件或者U盘将新的提交放在一个包里传回去。 69 | 70 | [source,console] 71 | ---- 72 | $ git log --oneline 73 | 71b84da last commit - second repo 74 | c99cf5b fourth commit - second repo 75 | 7011d3d third commit - second repo 76 | 9a466c5 second commit 77 | b1ec324 first commit 78 | ---- 79 | 80 | 首先我们需要确认我们希望被打包的提交区间。 81 | 和网络协议不太一样,网络协议会自动计算出所需传输的最小数据集,而我们需要手动计算。 82 | 当然你可以像上面那样将整个仓库打包,但最好仅仅打包变更的部分 —— 就是我们刚刚在本地做的 3 个提交。 83 | 84 | 为了实现这个目标,你需要计算出差别。 85 | 就像我们在 <<_commit_ranges>> 介绍的,你有很多种方式去指明一个提交区间。 86 | 我们可以使用 `origin/master..master` 或者 `master ^origin/master` 之类的方法来获取那 3 个在我们的 master 分支而不在原始仓库中的提交。 87 | 你可以用 `log` 命令来测试。 88 | 89 | [source,console] 90 | ---- 91 | $ git log --oneline master ^origin/master 92 | 71b84da last commit - second repo 93 | c99cf5b fourth commit - second repo 94 | 7011d3d third commit - second repo 95 | ---- 96 | 97 | 这样就获取到我们希望被打包的提交列表,让我们将这些提交打包。 98 | 我们可以用 `git bundle create` 命令,加上我们想用的文件名,以及要打包的提交区间。 99 | 100 | [source,console] 101 | ---- 102 | $ git bundle create commits.bundle master ^9a466c5 103 | Counting objects: 11, done. 104 | Delta compression using up to 2 threads. 105 | Compressing objects: 100% (3/3), done. 106 | Writing objects: 100% (9/9), 775 bytes, done. 107 | Total 9 (delta 0), reused 0 (delta 0) 108 | ---- 109 | 110 | 现在在我们的目录下会有一个 `commits.bundle` 文件。 111 | 如果我们把这个文件发送给我们的合作者,她可以将这个文件导入到原始的仓库中,即使在这期间已经有其他的工作提交到这个仓库中。 112 | 113 | 当她拿到这个包时,她可以在导入到仓库之前查看这个包里包含了什么内容。 114 | `bundle verify` 命令可以检查这个文件是否是一个合法的 Git 包,是否拥有共同的祖先来导入。 115 | 116 | [source,console] 117 | ---- 118 | $ git bundle verify ../commits.bundle 119 | The bundle contains 1 ref 120 | 71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master 121 | The bundle requires these 1 ref 122 | 9a466c572fe88b195efd356c3f2bbeccdb504102 second commit 123 | ../commits.bundle is okay 124 | ---- 125 | 126 | 如果打包工具仅仅把最后两个提交打包,而不是三个,原始的仓库是无法导入这个包的,因为这个包缺失了必要的提交记录。这时候 `verify` 的输出类似: 127 | 128 | [source,console] 129 | ---- 130 | $ git bundle verify ../commits-bad.bundle 131 | error: Repository lacks these prerequisite commits: 132 | error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo 133 | ---- 134 | 135 | 而我们的第一个包是合法的,所以我们可以从这个包里提取出提交。 136 | 如果你想查看这边包里可以导入哪些分支,同样有一个命令可以列出这些顶端: 137 | 138 | [source,console] 139 | ---- 140 | $ git bundle list-heads ../commits.bundle 141 | 71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master 142 | ---- 143 | 144 | `verify` 子命令同样可以告诉你有哪些顶端。 145 | 该功能的目的是查看哪些是可以被拉入的,所以你可以使用 `fetch` 或者 `pull` 命令从包中导入提交。 146 | 这里我们要从包中取出 `master` 分支到我们仓库中的 'other-master' 分支: 147 | 148 | [source,console] 149 | ---- 150 | $ git fetch ../commits.bundle master:other-master 151 | From ../commits.bundle 152 | * [new branch] master -> other-master 153 | ---- 154 | 155 | 可以看到我们已经将提交导入到 'other-master' 分支,以及在这期间我们自己在 'master' 分支上的提交。 156 | 157 | [source,console] 158 | ---- 159 | $ git log --oneline --decorate --graph --all 160 | * 8255d41 (HEAD, master) third commit - first repo 161 | | * 71b84da (other-master) last commit - second repo 162 | | * c99cf5b fourth commit - second repo 163 | | * 7011d3d third commit - second repo 164 | |/ 165 | * 9a466c5 second commit 166 | * b1ec324 first commit 167 | ---- 168 | 169 | 因此,当你在没有合适的网络或者可共享仓库的情况下,`git bundle` 很适合用于共享或者网络类型的操作。 170 | -------------------------------------------------------------------------------- /07-git-tools/sections/searching.adoc: -------------------------------------------------------------------------------- 1 | [[_searching]] 2 | === 搜索 3 | 4 | 无论仓库里的代码量有多少,你经常需要查找一个函数是在哪里调用或者定义的,或者一个方法的变更历史。 5 | Git 提供了两个有用的工具来快速地从它的数据库中浏览代码和提交。 6 | 我们来简单的看一下。 7 | 8 | [[_git_grep]] 9 | ==== Git Grep 10 | 11 | Git 提供了一个 `grep` 命令,你可以很方便地从提交历史或者工作目录中查找一个字符串或者正则表达式。 12 | 我们用 Git 本身源代码的查找作为例子。 13 | 14 | 默认情况下 Git 会查找你工作目录的文件。 15 | 你可以传入 `-n` 参数来输出 Git 所找到的匹配行行号。 16 | 17 | [source,console] 18 | ---- 19 | $ git grep -n gmtime_r 20 | compat/gmtime.c:3:#undef gmtime_r 21 | compat/gmtime.c:8: return git_gmtime_r(timep, &result); 22 | compat/gmtime.c:11:struct tm *git_gmtime_r(const time_t *timep, struct tm *result) 23 | compat/gmtime.c:16: ret = gmtime_r(timep, result); 24 | compat/mingw.c:606:struct tm *gmtime_r(const time_t *timep, struct tm *result) 25 | compat/mingw.h:162:struct tm *gmtime_r(const time_t *timep, struct tm *result); 26 | date.c:429: if (gmtime_r(&now, &now_tm)) 27 | date.c:492: if (gmtime_r(&time, tm)) { 28 | git-compat-util.h:721:struct tm *git_gmtime_r(const time_t *, struct tm *); 29 | git-compat-util.h:723:#define gmtime_r git_gmtime_r 30 | ---- 31 | 32 | `grep` 命令有一些有趣的选项。 33 | 34 | 例如,你可以使用 `--count` 选项来使 Git 输出概述的信息,仅仅包括哪些文件包含匹配以及每个文件包含了多少个匹配。 35 | 36 | [source,console] 37 | ---- 38 | $ git grep --count gmtime_r 39 | compat/gmtime.c:4 40 | compat/mingw.c:1 41 | compat/mingw.h:1 42 | date.c:2 43 | git-compat-util.h:2 44 | ---- 45 | 46 | 如果你想看匹配的行是属于哪一个方法或者函数,你可以传入 `-p` 选项: 47 | 48 | [source,console] 49 | ---- 50 | $ git grep -p gmtime_r *.c 51 | date.c=static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm) 52 | date.c: if (gmtime_r(&now, &now_tm)) 53 | date.c=static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt) 54 | date.c: if (gmtime_r(&time, tm)) { 55 | ---- 56 | 57 | 在这里我们可以看到在 date.c 文件中有 `match_multi_number` 和 `match_digit` 两个函数调用了 `gmtime_r`。 58 | 59 | 你还可以使用 `--and` 标志来查看复杂的字符串组合,也就是在同一行同时包含多个匹配。 60 | 比如,我们要查看在旧版本 1.8.0 的 Git 代码库中定义了常量名包含 ``LINK'' 或者 ``BUF_MAX'' 这两个字符串所在的行。 61 | 62 | 这里我们也用到了 `--break` 和 `--heading` 选项来使输出更加容易阅读。 63 | 64 | [source,console] 65 | ---- 66 | $ git grep --break --heading \ 67 | -n -e '#define' --and \( -e LINK -e BUF_MAX \) v1.8.0 68 | v1.8.0:builtin/index-pack.c 69 | 62:#define FLAG_LINK (1u<<20) 70 | 71 | v1.8.0:cache.h 72 | 73:#define S_IFGITLINK 0160000 73 | 74:#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK) 74 | 75 | v1.8.0:environment.c 76 | 54:#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS 77 | 78 | v1.8.0:strbuf.c 79 | 326:#define STRBUF_MAXLINK (2*PATH_MAX) 80 | 81 | v1.8.0:symlinks.c 82 | 53:#define FL_SYMLINK (1 << 2) 83 | 84 | v1.8.0:zlib.c 85 | 30:/* #define ZLIB_BUF_MAX ((uInt)-1) */ 86 | 31:#define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */ 87 | ---- 88 | 89 | 相比于一些常用的搜索命令比如 `grep` 和 `ack`,`git grep` 命令有一些的优点。 90 | 第一就是速度非常快,第二是你不仅仅可以可以搜索工作目录,还可以搜索任意的 Git 树。 91 | 在上一个例子中,我们在一个旧版本的 Git 源代码中查找,而不是当前检出的版本。 92 | 93 | ==== Git 日志搜索 94 | 95 | 或许你不想知道某一项在 **哪里** ,而是想知道是什么 **时候** 存在或者引入的。 96 | `git log` 命令有许多强大的工具可以通过提交信息甚至是 diff 的内容来找到某个特定的提交。 97 | 98 | 例如,如果我们想找到 `ZLIB_BUF_MAX` 常量是什么时候引入的,我们可以使用 `-S` 选项来显示新增和删除该字符串的提交。 99 | 100 | [source,console] 101 | ---- 102 | $ git log -SZLIB_BUF_MAX --oneline 103 | e01503b zlib: allow feeding more than 4GB in one go 104 | ef49a7a zlib: zlib can only process 4GB at a time 105 | ---- 106 | 107 | 如果我们查看这些提交的 diff,我们可以看到在 `ef49a7a` 这个提交引入了常量,并且在 `e01503b` 这个提交中被修改了。 108 | 109 | 如果你希望得到更精确的结果,你可以使用 `-G` 选项来使用正则表达式搜索。 110 | 111 | ===== 行日志搜索 112 | 113 | 行日志搜索是另一个相当高级并且有用的日志搜索功能。 114 | 这是一个最近新增的不太知名的功能,但却是十分有用。 115 | 在 `git log` 后加上 `-L` 选项即可调用,它可以展示代码中一行或者一个函数的历史。 116 | 117 | 例如,假设我们想查看 `zlib.c` 文件中`git_deflate_bound` 函数的每一次变更,我们可以执行 `git log -L :git_deflate_bound:zlib.c`。 118 | Git 会尝试找出这个函数的范围,然后查找历史记录,并且显示从函数创建之后一系列变更对应的补丁。 119 | 120 | [source,console] 121 | ---- 122 | $ git log -L :git_deflate_bound:zlib.c 123 | commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca 124 | Author: Junio C Hamano 125 | Date: Fri Jun 10 11:52:15 2011 -0700 126 | 127 | zlib: zlib can only process 4GB at a time 128 | 129 | diff --git a/zlib.c b/zlib.c 130 | --- a/zlib.c 131 | +++ b/zlib.c 132 | @@ -85,5 +130,5 @@ 133 | -unsigned long git_deflate_bound(z_streamp strm, unsigned long size) 134 | +unsigned long git_deflate_bound(git_zstream *strm, unsigned long size) 135 | { 136 | - return deflateBound(strm, size); 137 | + return deflateBound(&strm->z, size); 138 | } 139 | 140 | 141 | commit 225a6f1068f71723a910e8565db4e252b3ca21fa 142 | Author: Junio C Hamano 143 | Date: Fri Jun 10 11:18:17 2011 -0700 144 | 145 | zlib: wrap deflateBound() too 146 | 147 | diff --git a/zlib.c b/zlib.c 148 | --- a/zlib.c 149 | +++ b/zlib.c 150 | @@ -81,0 +85,5 @@ 151 | +unsigned long git_deflate_bound(z_streamp strm, unsigned long size) 152 | +{ 153 | + return deflateBound(strm, size); 154 | +} 155 | + 156 | ---- 157 | 158 | 如果 Git 无法计算出如何匹配你代码中的函数或者方法,你可以提供一个正则表达式。 159 | 例如,这个命令和上面的是等同的:`git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c`。 160 | 你也可以提供单行或者一个范围的行号来获得相同的输出。 161 | -------------------------------------------------------------------------------- /07-git-tools/sections/subtree-merges.adoc: -------------------------------------------------------------------------------- 1 | [[_subtree_merge]] 2 | ===== 子树合并 3 | 4 | 子树合并的思想是你有两个项目,并且其中一个映射到另一个项目的一个子目录,或者反过来也行。 5 | 当你执行一个子树合并时,Git 通常可以自动计算出其中一个是另外一个的子树从而实现正确的合并。 6 | 7 | 我们来看一个例子如何将一个项目加入到一个已存在的项目中,然后将第二个项目的代码合并到第一个项目的子目录中。 8 | 9 | 首先,我们将 Rack 应用添加到你的项目里。 10 | 我们把 Rack 项目作为一个远程的引用添加到我们的项目里,然后检出到它自己的分支。 11 | 12 | [source,console] 13 | ---- 14 | $ git remote add rack_remote https://github.com/rack/rack 15 | $ git fetch rack_remote 16 | warning: no common commits 17 | remote: Counting objects: 3184, done. 18 | remote: Compressing objects: 100% (1465/1465), done. 19 | remote: Total 3184 (delta 1952), reused 2770 (delta 1675) 20 | Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done. 21 | Resolving deltas: 100% (1952/1952), done. 22 | From https://github.com/rack/rack 23 | * [new branch] build -> rack_remote/build 24 | * [new branch] master -> rack_remote/master 25 | * [new branch] rack-0.4 -> rack_remote/rack-0.4 26 | * [new branch] rack-0.9 -> rack_remote/rack-0.9 27 | $ git checkout -b rack_branch rack_remote/master 28 | Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master. 29 | Switched to a new branch "rack_branch" 30 | ---- 31 | 32 | 现在在我们的 `rack_branch` 分支里就有 Rack 项目的根目录,而我们的项目则在 `master` 分支里。 33 | 如果你从一个分支切换到另一个分支,你可以看到它们的项目根目录是不同的: 34 | 35 | [source,console] 36 | ---- 37 | $ ls 38 | AUTHORS KNOWN-ISSUES Rakefile contrib lib 39 | COPYING README bin example test 40 | $ git checkout master 41 | Switched to branch "master" 42 | $ ls 43 | README 44 | ---- 45 | 46 | 这个是一个比较奇怪的概念。 47 | 并不是仓库中的所有分支都是必须属于同一个项目的分支. 48 | 这并不常见,因为没啥用,但是却是在不同分支里包含两条完全不同提交历史的最简单的方法。 49 | 50 | 在这个例子中,我们希望将 Rack 项目拉到 `master` 项目中作为一个子目录。 51 | 我们可以在 Git 中执行 `git read-tree` 来实现。 52 | 你可以在 <<_git_internals>> 中查看更多 `read-tree` 的相关信息,现在你只需要知道它会读取一个分支的根目录树到当前的暂存区和工作目录里。 53 | 先切回你的 `master` 分支,将 `rack_back` 分支拉取到我们项目的 `master` 分支中的 `rack` 子目录。 54 | 55 | [source,console] 56 | ---- 57 | $ git read-tree --prefix=rack/ -u rack_branch 58 | ---- 59 | 60 | 当我们提交时,那个子目录中拥有所有 Rack 项目的文件 —— 就像我们直接从压缩包里复制出来的一样。 61 | 有趣的是你可以很容易地将一个分支的变更合并到另一个分支里。 62 | 所以,当 Rack 项目有更新时,我们可以切换到那个分支来拉取上游的变更。 63 | 64 | [source,console] 65 | ---- 66 | $ git checkout rack_branch 67 | $ git pull 68 | ---- 69 | 70 | 接着,我们可以将这些变更合并回我们的 `master` 分支。 71 | 使用 `--squash` 选项和使用 `-Xsubtree` 选项(它采用递归合并策略),都可以用来可以拉取变更并且预填充提交信息。 72 | (递归策略在这里是默认的,提到它是为了让读者有个清晰的概念。) 73 | 74 | [source,console] 75 | ---- 76 | $ git checkout master 77 | $ git merge --squash -s recursive -Xsubtree=rack rack_branch 78 | Squash commit -- not updating HEAD 79 | Automatic merge went well; stopped before committing as requested 80 | ---- 81 | 82 | Rack 项目中所有的改动都被合并了,等待被提交到本地。 83 | 你也可以用相反的方法——在 master 分支上的 `rack` 子目录中做改动然后将它们合并入你的 `rack_branch` 分支中,之后你可能将其提交给项目维护着或者将它们推送到上游。 84 | 85 | 这给我们提供了一种类似子模块工作流的工作方式,但是它并不需要用到子模块(有关子模块的内容我们会在 <<_git_submodules>> 中介绍)。 86 | 我们可以在自己的仓库中保持一些和其他项目相关的分支,偶尔使用子树合并将它们合并到我们的项目中。 87 | 某些时候这种方式很有用,例如当所有的代码都提交到一个地方的时候。 88 | 然而,它同时也有缺点,它更加复杂且更容易让人犯错,例如重复合并改动或者不小心将分支提交到一个无关的仓库上去。 89 | 90 | 另外一个有点奇怪的地方是,当你想查看 `rack` 子目录和 `rack_branch` 分支的差异——来确定你是否需要合并它们——你不能使用普通的 `diff` 命令。 91 | 取而代之的是,你必须使用 `git diff-tree` 来和你的目标分支做比较: 92 | 93 | [source,console] 94 | ---- 95 | $ git diff-tree -p rack_branch 96 | ---- 97 | 98 | 或者,将你的 `rack` 子目和最近一次从服务器上抓取的 `master` 分支进行比较,你可以运行: 99 | 100 | [source,console] 101 | ---- 102 | $ git diff-tree -p rack_remote/master 103 | ---- 104 | -------------------------------------------------------------------------------- /07-git-tools/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 你已经接触了很多能够精确地操控提交和暂存区的高级工具。 4 | 当你碰到问题时,你应该可以很容易找出是哪个分支在什么时候由谁引入了它们。 5 | 如果你想在项目中使用子项目,你也已经知道如何来满足这些需求。 6 | 到此,你应该能毫无压力地在命令行中使用 Git 来完成日常中的大部分事情。 7 | -------------------------------------------------------------------------------- /08-customizing-git/1-customizing-git.adoc: -------------------------------------------------------------------------------- 1 | [[_customizing_git]] 2 | == 自定义 Git 3 | 4 | 到目前为止,我们已经阐述了 Git 基本的运作机制和使用方式,介绍了许多 Git 提供的工具来帮助你简单且有效地使用它。 5 | 在本章,我们将演示如何借助 Git 的一些重要的配置方法和钩子机制,来满足自定义的需求。 6 | 通过这些工具,它会和你、你的公司或你的团队配合得天衣无缝。 7 | -------------------------------------------------------------------------------- /08-customizing-git/images/clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/08-customizing-git/images/clean.png -------------------------------------------------------------------------------- /08-customizing-git/images/p4merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/08-customizing-git/images/p4merge.png -------------------------------------------------------------------------------- /08-customizing-git/images/smudge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/08-customizing-git/images/smudge.png -------------------------------------------------------------------------------- /08-customizing-git/sections/hooks.adoc: -------------------------------------------------------------------------------- 1 | [[_git_hooks]] 2 | === Git 钩子 3 | 4 | (((hooks))) 5 | 和其它版本控制系统一样,Git 能在特定的重要动作发生时触发自定义脚本。 6 | 有两组这样的钩子:客户端的和服务器端的。 7 | 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。 8 | 你可以随心所欲地运用这些钩子。 9 | 10 | ==== 安装一个钩子 11 | 12 | 钩子都被存储在 Git 目录下的 `hooks` 子目录中。 13 | 也即绝大部分项目中的 `.git/hooks` 。 14 | 当你用 `git init` 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 15 | 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或其它语言编写它们。 16 | 这些示例的名字都是以 `.sample` 结尾,如果你想启用它们,得先移除这个后缀。 17 | 18 | 把一个正确命名且可执行的文件放入 Git 目录下的 `hooks` 子目录中,即可激活该钩子脚本。 19 | 这样一来,它就能被 Git 调用。 20 | 接下来,我们会讲解常用的钩子脚本类型。 21 | 22 | ==== 客户端钩子 23 | 24 | 客户端钩子分为很多种。 25 | 下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。 26 | 27 | [NOTE] 28 | ==== 29 | 需要注意的是,克隆某个版本库时,它的客户端钩子 *并不* 随同复制。 30 | 如果需要靠这些脚本来强制维持某种策略,建议你在服务器端实现这一功能。(请参照 <<_an_example_git_enforced_policy>> 中的例子。) 31 | ==== 32 | 33 | ===== 提交工作流钩子 34 | 35 | 前四个钩子涉及提交的过程。 36 | 37 | `pre-commit` 钩子在键入提交信息前运行。 38 | 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 39 | 如果该钩子以非零值退出,Git 将放弃此次提交,不过你可以用 `git commit --no-verify` 来绕过这个环节。 40 | 你可以利用该钩子,来检查代码风格是否一致(运行类似 `lint` 的程序)、尾随空白字符是否存在(自带的钩子就是这么做的),或新方法的文档是否适当。 41 | 42 | `prepare-commit-msg` 钩子在启动提交信息编辑器之前,默认信息被创建之后运行。 43 | 它允许你编辑提交者所看到的默认信息。 44 | 该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。 45 | 它对一般的提交来说并没有什么用;然而对那些会自动产生默认信息的提交,如提交信息模板、合并提交、压缩提交和修订提交等非常实用。 46 | 你可以结合提交模板来使用它,动态地插入信息。 47 | 48 | `commit-msg` 钩子接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径。 49 | 如果该钩子脚本以非零值退出,Git 将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。 50 | 在本章的最后一节,我们将展示如何使用该钩子来核对提交信息是否遵循指定的模板。 51 | 52 | `post-commit` 钩子在整个提交过程完成后运行。 53 | 它不接收任何参数,但你可以很容易地通过运行 `git log -1 HEAD` 来获得最后一次的提交信息。 54 | 该钩子一般用于通知之类的事情。 55 | 56 | [[_email_hooks]] 57 | ===== 电子邮件工作流钩子 58 | 59 | 你可以给电子邮件工作流设置三个客户端钩子。 60 | 它们都是由 `git am` 命令调用的,因此如果你没有在你的工作流中用到这个命令,可以跳到下一节。 61 | 如果你需要通过电子邮件接收由 `git format-patch` 产生的补丁,这些钩子也许用得上。 62 | 63 | 第一个运行的钩子是 `applypatch-msg` 。 64 | 它接收单个参数:包含请求合并信息的临时文件的名字。 65 | 如果脚本返回非零值,Git 将放弃该补丁。 66 | 你可以用该脚本来确保提交信息符合格式,或直接用脚本修正格式错误。 67 | 68 | 下一个在 `git am` 运行期间被调用的是 `pre-applypatch` 。 69 | 有些难以理解的是,它正好运行于应用补丁 _之后_,产生提交之前,所以你可以用它在提交前检查快照。 70 | 你可以用这个脚本运行测试或检查工作区。 71 | 如果有什么遗漏,或测试未能通过,脚本会以非零值退出,中断 `git am` 的运行,这样补丁就不会被提交。 72 | 73 | `post-applypatch` 运行于提交产生之后,是在 `git am` 运行期间最后被调用的钩子。 74 | 你可以用它把结果通知给一个小组或所拉取的补丁的作者。 75 | 但你没办法用它停止打补丁的过程。 76 | 77 | [[_other_client_hooks]] 78 | ===== 其它客户端钩子 79 | 80 | `pre-rebase` 钩子运行于变基之前,以非零值退出可以中止变基的过程。 81 | 你可以使用这个钩子来禁止对已经推送的提交变基。 82 | Git 自带的 `pre-rebase` 钩子示例就是这么做的,不过它所做的一些假设可能与你的工作流程不匹配。 83 | 84 | `post-rewrite` 钩子被那些会替换提交记录的命令调用,比如 `git commit --amend` 和 `git rebase`(不过不包括 `git filter-branch`)。 85 | 它唯一的参数是触发重写的命令名,同时从标准输入中接受一系列重写的提交记录。 86 | 这个钩子的用途很大程度上跟 `post-checkout` 和 `post-merge` 差不多。 87 | 88 | 在 `git checkout` 成功运行后,`post-checkout` 钩子会被调用。你可以根据你的项目环境用它调整你的工作目录。 89 | 其中包括放入大的二进制文件、自动生成文档或进行其他类似这样的操作。 90 | 91 | 在 `git merge` 成功运行后,`post-merge` 钩子会被调用。 92 | 你可以用它恢复 Git 无法跟踪的工作区数据,比如权限数据。 93 | 这个钩子也可以用来验证某些在 Git 控制之外的文件是否存在,这样你就能在工作区改变时,把这些文件复制进来。 94 | 95 | `pre-push` 钩子会在 `git push` 运行期间, 更新了远程引用但尚未传送对象时被调用。 96 | 它接受远程分支的名字和位置作为参数,同时从标准输入中读取一系列待更新的引用。 97 | 你可以在推送开始之前,用它验证对引用的更新操作(一个非零的退出码将终止推送过程)。 98 | 99 | Git 的一些日常操作在运行时,偶尔会调用 `git gc --auto` 进行垃圾回收。 100 | `pre-auto-gc` 钩子会在垃圾回收开始之前被调用,可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收。 101 | 102 | ==== 服务器端钩子 103 | 104 | 除了客户端钩子,作为系统管理员,你还可以使用若干服务器端的钩子对项目强制执行各种类型的策略。 105 | 这些钩子脚本在推送到服务器之前和之后运行。 106 | 推送到服务器前运行的钩子可以在任何时候以非零值退出,拒绝推送并给客户端返回错误消息,还可以依你所想设置足够复杂的推送策略。 107 | 108 | ===== `pre-receive` 109 | 110 | 处理来自客户端的推送操作时,最先被调用的脚本是 `pre-receive`。 111 | 它从标准输入获取一系列被推送的引用。如果它以非零值退出,所有的推送内容都不会被接受。 112 | 你可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制。 113 | 114 | ===== `update` 115 | 116 | `update` 脚本和 `pre-receive` 脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。 117 | 假如推送者同时向多个分支推送内容,`pre-receive` 只运行一次,相比之下 `update` 则会为每一个被推送的分支各运行一次。 118 | 它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的 SHA-1 值,以及用户准备推送的内容的 SHA-1 值。 119 | 如果 update 脚本以非零值退出,只有相应的那一个引用会被拒绝;其余的依然会被更新。 120 | 121 | ===== `post-receive` 122 | 123 | `post-receive` 挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。 124 | 它接受与 `pre-receive` 相同的标准输入数据。 125 | 它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器,或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。 126 | 该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态,所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间。 127 | -------------------------------------------------------------------------------- /08-customizing-git/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 我们已经阐述了大部分通过自定义 Git 客户端和服务端来适应自己工作流程和项目内容的方式。 4 | 你已经学到各种各样的设置项、基于文件的选项和事件钩子,还建立了一个示例用的强制策略服务器。 5 | 无论创造出了什么样的工作流程,你都能使 Git 与它珠联璧合。 6 | -------------------------------------------------------------------------------- /09-git-and-other-scms/1-git-and-other-scms.adoc: -------------------------------------------------------------------------------- 1 | == Git 与其他系统 2 | 3 | 现实并不总是尽如人意。 4 | 通常,你不能立刻就把接触到的每一个项目都切换到 Git。 5 | 有时候你被困在使用其他 VCS 的项目中,却希望使用 Git。 6 | 在本章的第一部分我们将会了解到,怎样在你的那些托管在不同系统的项目上使用 Git 客户端。 7 | 8 | 在某些时候,你可能想要将已有项目转换到 Git。 9 | 本章的第二部分涵盖了从几个特定系统将你的项目迁移至 Git 的方法,即使没有预先构建好的导入工具,我们也有办法手动导入。 10 | -------------------------------------------------------------------------------- /09-git-and-other-scms/images/git-fusion-boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/09-git-and-other-scms/images/git-fusion-boot.png -------------------------------------------------------------------------------- /09-git-and-other-scms/images/git-fusion-perforce-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/09-git-and-other-scms/images/git-fusion-perforce-graph.png -------------------------------------------------------------------------------- /09-git-and-other-scms/images/git-tfs-ct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/09-git-and-other-scms/images/git-tfs-ct.png -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/git-client.adoc: -------------------------------------------------------------------------------- 1 | === 作为客户端的 Git 2 | 3 | (((Git as a client))) 4 | Git 为开发者提供了如此优秀的体验,许多人已经找到了在他们的工作站上使用 Git 的方法,即使他们团队其余的人使用的是完全不同的 VCS。 5 | 有许多这种可用的适配器,它们被叫做 ``桥接''。 6 | 下面我们将要介绍几个很可能会在实际中用到的桥接。 7 | 8 | {% include "./client-svn.adoc" %} 9 | 10 | {% include "./client-hg.adoc" %} 11 | 12 | {% include "./client-p4.adoc" %} 13 | 14 | {% include "./client-tfs.adoc" %} 15 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/git-migrate.adoc: -------------------------------------------------------------------------------- 1 | [[_migrating]] 2 | === 迁移到 Git 3 | 4 | (((Migrating to Git))) 5 | 如果你现在有一个正在使用其他 VCS 的代码库,但是你已经决定开始使用 Git,必须通过某种方式将你的项目迁移至 Git。 6 | 这一部分会介绍一些通用系统的导入器,然后演示如何开发你自己定制的导入器。 7 | 你将会学习如何从几个大型专业应用的 SCM 系统中导入数据,不仅因为它们是大多数想要转换的用户正在使用的系统,也因为获取针对它们的高质量工具很容易。 8 | 9 | {% include "./import-svn.adoc" %} 10 | 11 | {% include "./import-hg.adoc" %} 12 | 13 | {% include "./import-p4.adoc" %} 14 | 15 | {% include "./import-tfs.adoc" %} 16 | 17 | {% include "./import-custom.adoc" %} 18 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/import-hg.adoc: -------------------------------------------------------------------------------- 1 | ==== Mercurial 2 | 3 | (((Mercurial)))(((Importing, from Mercurial))) 4 | 因为 Mercurial 与 Git 在表示版本时有着非常相似的模型,也因为 Git 拥有更加强大的灵活性,将一个仓库从 Mercurial 转换到 Git 是相当直接的,使用一个叫作“hg-fast-export”的工具,需要从这里拷贝一份: 5 | 6 | [source,console] 7 | ---- 8 | $ git clone http://repo.or.cz/r/fast-export.git /tmp/fast-export 9 | ---- 10 | 11 | 转换的第一步就是要先得到想要转换的 Mercurial 仓库的完整克隆: 12 | 13 | [source,console] 14 | ---- 15 | $ hg clone /tmp/hg-repo 16 | ---- 17 | 18 | 下一步就是创建一个作者映射文件。 19 | Mercurial 对放入到变更集作者字段的内容比 Git 更宽容一些,所以这是一个清理的好机会。 20 | 只需要用到 `bash` 终端下的一行命令: 21 | 22 | [source,console] 23 | ---- 24 | $ cd /tmp/hg-repo 25 | $ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors 26 | ---- 27 | 28 | 这会花费几秒钟,具体要看项目提交历史有多少,最终 `/tmp/authors` 文件看起来会像这样: 29 | 30 | [source] 31 | ---- 32 | bob 33 | bob@localhost 34 | bob 35 | bob jones company com> 36 | Bob Jones 37 | Joe Smith 38 | ---- 39 | 40 | 在这个例子中,同一个人(Bob)使用不同的名字创建变更集,其中一个实际上是正确的,另一个完全不符合 Git 提交的规范。 41 | Hg-fast-export 通过向我们想要修改的行尾添加 `={new name and email address}` 来修正这个问题,移除任何我们想要保留的用户名所在的行。 42 | 如果所有的用户名看起来都是正确的,那我们根本就不需要这个文件。 43 | 在本例中,我们会使文件看起来像这样: 44 | 45 | [source] 46 | ---- 47 | bob=Bob Jones 48 | bob@localhost=Bob Jones 49 | bob jones company com>=Bob Jones 50 | bob =Bob Jones 51 | ---- 52 | 53 | 下一步是创建一个新的 Git 仓库,然后运行导出脚本: 54 | 55 | [source,console] 56 | ---- 57 | $ git init /tmp/converted 58 | $ cd /tmp/converted 59 | $ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors 60 | ---- 61 | 62 | `-r` 选项告诉 hg-fast-export 去哪里寻找我们想要转换的 Mercurial 仓库,`-A` 标记告诉它在哪找到作者映射文件。 63 | 这个脚本会分析 Mercurial 变更集然后将它们转换成 Git“fast-import”功能(我们将在之后详细讨论)需要的脚本。 64 | 这会花一点时间(尽管它比通过网格 _更_ 快),输出相当的冗长: 65 | 66 | [source,console] 67 | ---- 68 | $ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors 69 | Loaded 4 authors 70 | master: Exporting full revision 1/22208 with 13/0/0 added/changed/removed files 71 | master: Exporting simple delta revision 2/22208 with 1/1/0 added/changed/removed files 72 | master: Exporting simple delta revision 3/22208 with 0/1/0 added/changed/removed files 73 | […] 74 | master: Exporting simple delta revision 22206/22208 with 0/4/0 added/changed/removed files 75 | master: Exporting simple delta revision 22207/22208 with 0/2/0 added/changed/removed files 76 | master: Exporting thorough delta revision 22208/22208 with 3/213/0 added/changed/removed files 77 | Exporting tag [0.4c] at [hg r9] [git :10] 78 | Exporting tag [0.4d] at [hg r16] [git :17] 79 | […] 80 | Exporting tag [3.1-rc] at [hg r21926] [git :21927] 81 | Exporting tag [3.1] at [hg r21973] [git :21974] 82 | Issued 22315 commands 83 | git-fast-import statistics: 84 | --------------------------------------------------------------------- 85 | Alloc'd objects: 120000 86 | Total objects: 115032 ( 208171 duplicates ) 87 | blobs : 40504 ( 205320 duplicates 26117 deltas of 39602 attempts) 88 | trees : 52320 ( 2851 duplicates 47467 deltas of 47599 attempts) 89 | commits: 22208 ( 0 duplicates 0 deltas of 0 attempts) 90 | tags : 0 ( 0 duplicates 0 deltas of 0 attempts) 91 | Total branches: 109 ( 2 loads ) 92 | marks: 1048576 ( 22208 unique ) 93 | atoms: 1952 94 | Memory total: 7860 KiB 95 | pools: 2235 KiB 96 | objects: 5625 KiB 97 | --------------------------------------------------------------------- 98 | pack_report: getpagesize() = 4096 99 | pack_report: core.packedGitWindowSize = 1073741824 100 | pack_report: core.packedGitLimit = 8589934592 101 | pack_report: pack_used_ctr = 90430 102 | pack_report: pack_mmap_calls = 46771 103 | pack_report: pack_open_windows = 1 / 1 104 | pack_report: pack_mapped = 340852700 / 340852700 105 | --------------------------------------------------------------------- 106 | 107 | $ git shortlog -sn 108 | 369 Bob Jones 109 | 365 Joe Smith 110 | ---- 111 | 112 | 那看起来非常好。 113 | 所有 Mercurial 标签都已被转换成 Git 标签,Mercurial 分支与书签都被转换成 Git 分支。 114 | 现在已经准备好将仓库推送到新的服务器那边: 115 | 116 | [source,console] 117 | ---- 118 | $ git remote add origin git@my-git-server:myrepository.git 119 | $ git push origin --all 120 | ---- 121 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/import-p4.adoc: -------------------------------------------------------------------------------- 1 | [[_perforce_import]] 2 | ==== Perforce 3 | 4 | (((Perforce)))(((Importing, from Perforce))) 5 | 下一个将要看到导入的系统是 Perforce。 6 | 就像我们之前讨论过的,有两种方式让 Git 与 Perforce 互相通信:git-p4 与 Perforce Git Fusion。 7 | 8 | ===== Perforce Git Fusion 9 | 10 | Git Fusion 使这个过程毫无痛苦。 11 | 只需要使用在 <<_p4_git_fusion>> 中讨论过的配置文件来配置你的项目设置、用户映射与分支,然后克隆整个仓库。 12 | Git Fusion 让你处在一个看起来像是原生 Git 仓库的环境中,如果愿意的话你可以随时将它推送到一个原生 Git 托管中。 13 | 如果你喜欢的话甚至可以使用 Perforce 作为你的 Git 托管。 14 | 15 | [[_git_p4]] 16 | ===== Git-p4 17 | 18 | Git-p4 也可以作为一个导入工具。 19 | 作为例子,我们将从 Perforce 公开仓库中导入 Jam 项目。 20 | 为了设置客户端,必须导出 P4PORT 环境变量指向 Perforce 仓库: 21 | 22 | [source,console] 23 | ---- 24 | $ export P4PORT=public.perforce.com:1666 25 | ---- 26 | 27 | [NOTE] 28 | ==== 29 | 为了继续后续步骤,需要连接到 Perforce 仓库。 30 | 在我们的例子中将会使用在 public.perforce.com 的公开仓库,但是你可以使用任何你有权限的仓库。 31 | ==== 32 | 33 | (((git commands, p4))) 34 | 运行 `git p4 clone` 命令从 Perforce 服务器导入 Jam 项目,提供仓库、项目路径与你想要存放导入项目的路径: 35 | 36 | [source,console] 37 | ---- 38 | $ git-p4 clone //guest/perforce_software/jam@all p4import 39 | Importing from //guest/perforce_software/jam@all into p4import 40 | Initialized empty Git repository in /private/tmp/p4import/.git/ 41 | Import destination: refs/remotes/p4/master 42 | Importing revision 9957 (100%) 43 | ---- 44 | 45 | 这个特定的项目只有一个分支,但是如果你在分支视图(或者说一些目录)中配置了一些分支,你可以将 `--detect-branches` 选项传递给 `git p4 clone` 来导入项目的所有分支。 46 | 查看 <<_git_p4_branches>> 来了解关于这点的更多信息。 47 | 48 | 此时你几乎已经完成了。 49 | 如果进入 `p4import` 目录中并运行 `git log`,可以看到你的导入工作: 50 | 51 | [source,console] 52 | ---- 53 | $ git log -2 54 | commit e5da1c909e5db3036475419f6379f2c73710c4e6 55 | Author: giles 56 | Date: Wed Feb 8 03:13:27 2012 -0800 57 | 58 | Correction to line 355; change to . 59 | 60 | [git-p4: depot-paths = "//public/jam/src/": change = 8068] 61 | 62 | commit aa21359a0a135dda85c50a7f7cf249e4f7b8fd98 63 | Author: kwirth 64 | Date: Tue Jul 7 01:35:51 2009 -0800 65 | 66 | Fix spelling error on Jam doc page (cummulative -> cumulative). 67 | 68 | [git-p4: depot-paths = "//public/jam/src/": change = 7304] 69 | ---- 70 | 71 | 你可以看到 `git-p4`在每一个提交里都留下了一个标识符。 72 | 如果之后想要引用 Perforce 的修改序号的话,标识符保留在那里也是可以的。 73 | 然而,如果想要移除标识符,现在正是这么做的时候 - 在你开始在新仓库中工作之前。 74 | (((git commands, filter-branch))) 75 | 可以使用 `git filter-branch` 将全部标识符移除。 76 | 77 | [source,console] 78 | ---- 79 | $ git filter-branch --msg-filter 'sed -e "/^\[git-p4:/d"' 80 | Rewrite e5da1c909e5db3036475419f6379f2c73710c4e6 (125/125) 81 | Ref 'refs/heads/master' was rewritten 82 | ---- 83 | 84 | 如果运行 `git log`,你会看到所有提交的 SHA-1 校验和都改变了,但是提交信息中不再有 `git-p4` 字符串了: 85 | 86 | [source,console] 87 | ---- 88 | $ git log -2 89 | commit b17341801ed838d97f7800a54a6f9b95750839b7 90 | Author: giles 91 | Date: Wed Feb 8 03:13:27 2012 -0800 92 | 93 | Correction to line 355; change to . 94 | 95 | commit 3e68c2e26cd89cb983eb52c024ecdfba1d6b3fff 96 | Author: kwirth 97 | Date: Tue Jul 7 01:35:51 2009 -0800 98 | 99 | Fix spelling error on Jam doc page (cummulative -> cumulative). 100 | ---- 101 | 102 | 现在导入已经准备好推送到你的新 Git 服务器上了。 103 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/import-svn.adoc: -------------------------------------------------------------------------------- 1 | ==== Subversion 2 | 3 | (((Subversion))) 4 | (((Importing, from Subversion))) 5 | 如果你阅读过前面关于 `git svn` 的章节,可以轻松地使用那些指令来 `git svn clone` 一个仓库,停止使用 Subversion 服务器,推送到一个新的 Git 服务器,然后就可以开始使用了。 6 | 如果你想要历史,可以从 Subversion 服务器上尽可能快地拉取数据来完成这件事(这可能会花费一些时间)。 7 | 8 | 然而,导入并不完美;因为花费太长时间了,你可能早已用其他方法完成导入操作。 9 | 导入产生的第一个问题就是作者信息。 10 | 在 Subversion 中,每一个人提交时都需要在系统中有一个用户,它会被记录在提交信息内。 11 | 在之前章节的例子中几个地方显示了 `schacon`,比如 `blame` 输出与 `git svn log`。 12 | 如果想要将上面的 Subversion 用户映射到一个更好的 Git 作者数据中,你需要一个 Subversion 用户到 Git 用户的映射。 13 | 创建一个 `users.txt` 的文件包含像下面这种格式的映射: 14 | 15 | [source] 16 | ---- 17 | schacon = Scott Chacon 18 | selse = Someo Nelse 19 | ---- 20 | 21 | 为了获得 SVN 使用的作者名字列表,可以运行这个: 22 | 23 | [source,console] 24 | ---- 25 | $ svn log --xml | grep author | sort -u | \ 26 | perl -pe 's/.*>(.*?)<.*/$1 = /' 27 | ---- 28 | 29 | 这会将日志输出为 XML 格式,然后保留作者信息行、去除重复、去除 XML 标记。 30 | (很显然这只会在安装了 `grep`、`sort` 与 `perl` 的机器上运行。) 31 | 然后,将输出重定向到你的 users.txt 文件中,这样就可以在每一个记录后面加入对应的 Git 用户数据。 32 | 33 | 你可以将此文件提供给 `git svn` 来帮助它更加精确地映射作者数据。 34 | 也可以通过传递 `--no-metadata` 给 `clone` 与 `init` 命令,告诉 `git svn` 不要包括 Subversion 通常会导入的元数据。 35 | 这会使你的 `import` 命令看起来像这样: 36 | 37 | [source,console] 38 | ---- 39 | $ git svn clone http://my-project.googlecode.com/svn/ \ 40 | --authors-file=users.txt --no-metadata -s my_project 41 | ---- 42 | 43 | 现在在 `my_project` 目录中应当有了一个更好的 Subversion 导入。 44 | 并不像是下面这样的提交: 45 | 46 | [source] 47 | ---- 48 | commit 37efa680e8473b615de980fa935944215428a35a 49 | Author: schacon 50 | Date: Sun May 3 00:12:22 2009 +0000 51 | 52 | fixed install - go to trunk 53 | 54 | git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de- 55 | be05-5f7a86268029 56 | ---- 57 | 58 | 反而它们看起来像是这样: 59 | 60 | [source] 61 | ---- 62 | commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2 63 | Author: Scott Chacon 64 | Date: Sun May 3 00:12:22 2009 +0000 65 | 66 | fixed install - go to trunk 67 | ---- 68 | 69 | 不仅是 Author 字段更好看了,`git-svn-id` 也不在了。 70 | 71 | 之后,你应当做一些导入后的清理工作。 72 | 第一步,你应当清理 `git svn` 设置的奇怪的引用。 73 | 首先移动标签,这样它们就是标签而不是奇怪的远程引用,然后你会移动剩余的分支这样它们就是本地的了。 74 | 75 | 为了将标签变为合适的 Git 标签,运行 76 | 77 | [source,console] 78 | ---- 79 | $ cp -Rf .git/refs/remotes/origin/tags/* .git/refs/tags/ 80 | $ rm -Rf .git/refs/remotes/origin/tags 81 | ---- 82 | 83 | 这会使原来在 `remotes/origin/tags/` 里的远程分支引用变成真正的(轻量)标签。 84 | 85 | 接下来,将 `refs/remotes` 下剩余的引用移动为本地分支: 86 | 87 | [source,console] 88 | ---- 89 | $ cp -Rf .git/refs/remotes/* .git/refs/heads/ 90 | $ rm -Rf .git/refs/remotes 91 | ---- 92 | 93 | 现在所有的旧分支都是真正的 Git 分支,并且所有的旧标签都是真正的 Git 标签。 94 | 最后一件要做的事情是,将你的新 Git 服务器添加为远程仓库并推送到上面。 95 | 下面是一个将你的服务器添加为远程仓库的例子: 96 | 97 | [source,console] 98 | ---- 99 | $ git remote add origin git@my-git-server:myrepository.git 100 | ---- 101 | 102 | 因为想要上传所有分支与标签,你现在可以运行: 103 | 104 | [source,console] 105 | ---- 106 | $ git push origin --all 107 | ---- 108 | 109 | 通过以上漂亮、干净地导入操作,你的所有分支与标签都应该在新 Git 服务器上。 110 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/import-tfs.adoc: -------------------------------------------------------------------------------- 1 | [[_git_tfs]] 2 | ==== TFS 3 | 4 | (((TFS)))(((Importing, from TFS))) 5 | 如果你的团队正在将他们的源代码管理从 TFVC 转换为 Git,你们会想要最高程度的无损转换。 6 | 这意味着,虽然我们在之前的交互章节介绍了 git-tfs 与 git-tf 两种工具,但是我们在本部分只能介绍 git-tfs,因为 git-tfs 支持分支,而使用 git-tf 代价太大。 7 | 8 | [NOTE] 9 | ==== 10 | 这是一个单向转换。 11 | 这意味着 Git 仓库无法连接到原始的 TFVC 项目。 12 | ==== 13 | 14 | 第一件事是映射用户名。 15 | TFVC 对待变更集作者字段的内容相当宽容,但是 Git 需要人类可读的名字与邮箱地址。 16 | 可以通过 `tf` 命令行客户端来获取这个信息,像这样: 17 | 18 | [source,powershell] 19 | ---- 20 | PS> tf history $/myproject -recursive > AUTHORS_TMP 21 | ---- 22 | 23 | 这会将历史中的所有变更集抓取下来并放到 AUTHORS_TMP 文件中,然后我们将会将 `User` 列(第二个)取出来。 24 | 打开文件找到列开始与结束的字符并替换,在下面的命令行中,`cut` 命令的参数 `11-20` 就是我们找到的: 25 | 26 | [source,powershell] 27 | ---- 28 | PS> cat AUTHORS_TMP | cut -b 11-20 | tail -n+3 | uniq | sort > AUTHORS 29 | ---- 30 | 31 | `cut` 命令只会保留每行中第 11 个到第 22 个字符。 32 | `tail` 命令会跳过前两行,就是字段表头与 ASCII 风格的下划线。 33 | 所有这些的结果通过管道送到 `uniq` 来去除重复,然后保存到 `AUTOHRS` 文件中。 34 | 下一步是手动的;为了让 git-tfs 有效地使用这个文件,每一行必须是这种格式: 35 | 36 | [source,text] 37 | ---- 38 | DOMAIN\username = User Name 39 | ---- 40 | 41 | 左边的部分是 TFVC 中的 ``User'' 字段,等号右边的部分是将被用作 Git 提交的用户名。 42 | 43 | 一旦有了这个文件,下一件事就是生成一个你需要的 TFVC 项目的完整克隆: 44 | 45 | [source,powershell] 46 | ---- 47 | PS> git tfs clone --with-branches --authors=AUTHORS https://username.visualstudio.com/DefaultCollection $/project/Trunk project_git 48 | ---- 49 | 50 | 接下来要从提交信息底部清理 `git-tfs-id` 区块。 51 | 下面的命令会完成这个任务: 52 | 53 | [source,powershell] 54 | ---- 55 | PS> git filter-branch -f --msg-filter 'sed "s/^git-tfs-id:.*$//g"' -- --all 56 | ---- 57 | 58 | 那会使用 Git 终端环境中的 `sed` 命令来将所有以 ``git-tfs-id:'' 开头的行替换为 Git 会忽略的空白。 59 | 60 | 全部完成后,你就已经准备好去增加一个新的远程仓库,推送你所有的分支上去,然后你的团队就可以开始用 Git 工作了。 61 | -------------------------------------------------------------------------------- /09-git-and-other-scms/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 你会觉得将 Git 作为其他版本控制系统的客户端,或者在数据无损的情况下将几乎任何一个现有的仓库导入到 Git,都是一件很惬意的事。 4 | 在下一章,我们将要讲解 Git 的原始内部数据,如果需要的话你就可以加工每一个字节。 5 | -------------------------------------------------------------------------------- /10-git-internals/1-git-internals.adoc: -------------------------------------------------------------------------------- 1 | [[_git_internals]] 2 | == Git 内部原理 3 | 4 | 无论是从之前的章节直接跳到本章,还是读完了其余章节一直到这——你都将在本章见识到 Git 的内部工作原理和实现方式。 5 | 我们发现学习这部分内容对于理解 Git 的用途和强大至关重要。不过也有人认为这些内容对于初学者而言可能难以理解且过于复杂。 6 | 因此我们把这部分内容放在最后一章,在学习过程中可以先阅读这部分,也可以晚点阅读这部分,这取决于你自己。 7 | 8 | 无论如何,既然已经读到了这里,就让我们开始吧。 9 | 首先要弄明白一点,从根本上来讲 Git 是一个内容寻址(content-addressable)文件系统,并在此之上提供了一个版本控制系统的用户界面。 10 | 马上你就会学到这意味着什么。 11 | 12 | 早期的 Git(主要是 1.5 之前的版本)的用户界面要比现在复杂的多,因为它更侧重于作为一个文件系统,而不是一个打磨过的版本控制系统。 13 | 不时会有一些陈词滥调抱怨早期那个晦涩复杂的 Git 用户界面;不过最近几年来,它已经被改进到不输于任何其他版本控制系统地清晰易用了。 14 | 15 | 内容寻址文件系统层是一套相当酷的东西,所以在本章我们会先讲解这部分内容。随后我们会学习传输机制和版本库管理任务——你迟早会和它们打交道。 16 | -------------------------------------------------------------------------------- /10-git-internals/images/data-model-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/10-git-internals/images/data-model-1.png -------------------------------------------------------------------------------- /10-git-internals/images/data-model-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/10-git-internals/images/data-model-2.png -------------------------------------------------------------------------------- /10-git-internals/images/data-model-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/10-git-internals/images/data-model-3.png -------------------------------------------------------------------------------- /10-git-internals/images/data-model-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/10-git-internals/images/data-model-4.png -------------------------------------------------------------------------------- /10-git-internals/sections/plumbing-porcelain.adoc: -------------------------------------------------------------------------------- 1 | [[_plumbing_porcelain]] 2 | === 底层命令和高层命令 3 | 4 | 本书旨在讨论如何通过 `checkout`、`branch`、`remote` 等大约 30 个诸如此类动词形式的命令来玩转 Git。 5 | 然而,由于 Git 最初是一套面向版本控制系统的工具集,而不是一个完整的、用户友好的版本控制系统,所以它还包含了一部分用于完成底层工作的命令。 6 | 这些命令被设计成能以 UNIX 命令行的风格连接在一起,抑或藉由脚本调用,来完成工作。 7 | 这部分命令一般被称作“底层(plumbing)”命令,而那些更友好的命令则被称作“高层(porcelain)”命令。 8 | 9 | 本书前九章专注于探讨高层命令。 10 | 然而在本章,我们将主要面对底层命令。 11 | 因为,底层命令得以让你窥探 Git 内部的工作机制,也有助于说明 Git 是如何完成工作的,以及它为何如此运作。 12 | 多数底层命令并不面向最终用户:它们更适合作为新命令和自定义脚本的组成部分。 13 | 14 | 当在一个新目录或已有目录执行 `git init` 时,Git 会创建一个 `.git` 目录。 15 | 这个目录包含了几乎所有 Git 存储和操作的对象。 16 | 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。 17 | 本章探讨的所有内容,均位于这个目录内。 18 | 该目录的结构如下所示: 19 | 20 | [source,console] 21 | ---- 22 | $ ls -F1 23 | HEAD 24 | config* 25 | description 26 | hooks/ 27 | info/ 28 | objects/ 29 | refs/ 30 | ---- 31 | 32 | 该目录下可能还会包含其他文件,不过对于一个全新的 `git init` 版本库,这将是你看到的默认结构。 33 | `description` 文件仅供 GitWeb 程序使用,我们无需关心。 34 | `config` 文件包含项目特有的配置选项。 35 | `info` 目录包含一个全局性排除(global exclude)文件(((excludes))),用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns)。 36 | `hooks` 目录包含客户端或服务端的钩子脚本(hook scripts),在 <<_git_hooks>> 中这部分话题已被详细探讨过。 37 | 38 | 剩下的四个条目很重要:`HEAD` 文件、(尚待创建的)`index` 文件,和 `objects` 目录、`refs` 目录。 39 | 这些条目是 Git 的核心组成部分。 40 | `objects` 目录存储所有数据内容;`refs` 目录存储指向数据(分支)的提交对象的指针;`HEAD` 文件指示目前被检出的分支;`index` 文件保存暂存区信息。 41 | 我们将详细地逐一检视这四部分,以期理解 Git 是如何运转的。 42 | -------------------------------------------------------------------------------- /10-git-internals/sections/refspec.adoc: -------------------------------------------------------------------------------- 1 | [[_refspec]] 2 | === 引用规格 3 | 4 | 纵观全书,我们已经使用过一些诸如远程分支到本地引用的简单映射方式,但这种映射可以更复杂。 5 | 假设你添加了这样一个远程版本库: 6 | 7 | [source,console] 8 | ---- 9 | $ git remote add origin https://github.com/schacon/simplegit-progit 10 | ---- 11 | 12 | 上述命令会在你的 `.git/config` 文件中添加一个小节,并在其中指定远程版本库的名称(`origin`)、URL 和一个用于获取操作的引用规格(refspec): 13 | 14 | [source,ini] 15 | ---- 16 | [remote "origin"] 17 | url = https://github.com/schacon/simplegit-progit 18 | fetch = +refs/heads/*:refs/remotes/origin/* 19 | ---- 20 | 21 | 引用规格的格式由一个可选的 `+` 号和紧随其后的 `:` 组成,其中 `` 是一个模式(pattern),代表远程版本库中的引用;`` 是那些远程引用在本地所对应的位置。 22 | `+` 号告诉 Git 即使在不能快进的情况下也要(强制)更新引用。 23 | 24 | 默认情况下,引用规格由 `git remote add` 命令自动生成, Git 获取服务器中 `refs/heads/` 下面的所有引用,并将它写入到本地的 `refs/remotes/origin/` 中。 25 | 所以,如果服务器上有一个 `master` 分支,我们可以在本地通过下面这种方式来访问该分支上的提交记录: 26 | 27 | [source,console] 28 | ---- 29 | $ git log origin/master 30 | $ git log remotes/origin/master 31 | $ git log refs/remotes/origin/master 32 | ---- 33 | 34 | 上面的三个命令作用相同,因为 Git 会把它们都扩展成 `refs/remotes/origin/master`。 35 | 36 | 如果想让 Git 每次只拉取远程的 `master` 分支,而不是所有分支,可以把(引用规格的)获取那一行修改为: 37 | 38 | [source] 39 | ---- 40 | fetch = +refs/heads/master:refs/remotes/origin/master 41 | ---- 42 | 43 | 这仅是针对该远程版本库的 `git fetch` 操作的默认引用规格。 44 | 如果有某些只希望被执行一次的操作,我们也可以在命令行指定引用规格。 45 | 若要将远程的 `master` 分支拉到本地的 `origin/mymaster` 分支,可以运行: 46 | 47 | [source,console] 48 | ---- 49 | $ git fetch origin master:refs/remotes/origin/mymaster 50 | ---- 51 | 52 | 你也可以指定多个引用规格。 53 | 在命令行中,你可以按照如下的方式拉取多个分支: 54 | 55 | [source,console] 56 | ---- 57 | $ git fetch origin master:refs/remotes/origin/mymaster \ 58 | topic:refs/remotes/origin/topic 59 | From git@github.com:schacon/simplegit 60 | ! [rejected] master -> origin/mymaster (non fast forward) 61 | * [new branch] topic -> origin/topic 62 | ---- 63 | 64 | 在这个例子中,对 `master` 分支的拉取操作被拒绝,因为它不是一个可以快进的引用。 65 | 我们可以通过在引用规格之前指定 `+` 号来覆盖该规则。 66 | 67 | 你也可以在配置文件中指定多个用于获取操作的引用规格。 68 | 如果想在每次获取时都包括 `master` 和 `experiment` 分支,添加如下两行: 69 | 70 | [source,ini] 71 | ---- 72 | [remote "origin"] 73 | url = https://github.com/schacon/simplegit-progit 74 | fetch = +refs/heads/master:refs/remotes/origin/master 75 | fetch = +refs/heads/experiment:refs/remotes/origin/experiment 76 | ---- 77 | 78 | 我们不能在模式中使用部分通配符,所以像下面这样的引用规格是不合法的: 79 | 80 | [source] 81 | ---- 82 | fetch = +refs/heads/qa*:refs/remotes/origin/qa* 83 | ---- 84 | 85 | 但我们可以使用命名空间(或目录)来达到类似目的。 86 | 假设你有一个 QA 团队,他们推送了一系列分支,同时你只想要获取 `master` 和 QA 团队的所有分支而不关心其他任何分支,那么可以使用如下配置: 87 | 88 | [source,ini] 89 | ---- 90 | [remote "origin"] 91 | url = https://github.com/schacon/simplegit-progit 92 | fetch = +refs/heads/master:refs/remotes/origin/master 93 | fetch = +refs/heads/qa/*:refs/remotes/origin/qa/* 94 | ---- 95 | 96 | 如果项目的工作流很复杂,有 QA 团队推送分支、开发人员推送分支、集成团队推送并且在远程分支上展开协作,你就可以像这样(在本地)为这些分支创建各自的命名空间,非常方便。 97 | 98 | [[_pushing_refspecs]] 99 | ==== 引用规格推送 100 | 101 | 像上面这样从远程版本库获取已在命名空间中的引用当然很棒,但 QA 团队最初应该如何将他们的分支放入远程的 `qa/` 命名空间呢? 102 | 我们可以通过引用规格推送来完成这个任务。 103 | 104 | 如果 QA 团队想把他们的 `master` 分支推送到远程服务器的 `qa/master` 分支上,可以运行: 105 | 106 | [source,console] 107 | ---- 108 | $ git push origin master:refs/heads/qa/master 109 | ---- 110 | 111 | 如果他们希望 Git 每次运行 `git push origin` 时都像上面这样推送,可以在他们的配置文件中添加一条 `push` 值: 112 | 113 | [source,ini] 114 | ---- 115 | [remote "origin"] 116 | url = https://github.com/schacon/simplegit-progit 117 | fetch = +refs/heads/*:refs/remotes/origin/* 118 | push = refs/heads/master:refs/heads/qa/master 119 | ---- 120 | 121 | 正如刚才所指出的,这会让 `git push origin` 默认把本地 `master` 分支推送到远程 `qa/master` 分支。 122 | 123 | ==== 删除引用 124 | 125 | 你还可以借助类似下面的命令通过引用规格从远程服务器上删除引用: 126 | 127 | [source,console] 128 | ---- 129 | $ git push origin :topic 130 | ---- 131 | 132 | 因为引用规格(的格式)是 `:`,所以上述命令把 `` 留空,意味着把远程版本库的 `topic` 分支定义为空值,也就是删除它。 133 | -------------------------------------------------------------------------------- /10-git-internals/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 现在,你应该相当了解 Git 在背后都做了些什么工作,并且在一定程度上也知道了 Git 是如何实现的。 4 | 本章讨论了很多底层命令,这些命令比我们在本书其余部分学到的高层命令来得更原始,也更简洁。 5 | 从底层了解 Git 的工作原理有助于更好地理解 Git 在内部是如何运作的,也方便你能够针对特定的工作流写出自己的工具和脚本。 6 | 7 | 作为一套内容寻址文件系统,Git 不仅仅是一个版本控制系统,它同时是一个非常强大且易用的工具。 8 | 我们希望你可以借助新学到的 Git 内部原理相关知识来实现出自己的应用,并且以更高级、更得心应手的方式来驾驭 Git。 9 | -------------------------------------------------------------------------------- /A-git-in-other-environments/1-git-other-environments.adoc: -------------------------------------------------------------------------------- 1 | [appendix] 2 | == 其它环境中的 Git 3 | 4 | 从头至尾读到了这里,你肯定已经掌握了不少使用 Git 命令行操作的知识。 5 | 你学会了操作本地文件,通过网络连接你的仓库,以及与他人进行有效率的合作。 6 | 但是故事并未就此结束;Git 通常只是更大的生态圈的一部分,在某些情况下使用终端并不是最合适的方式。 7 | 现在就让我们来了解一下如何在其它类型的环境中更好地使用 Git,以及别的应用(包括你的)如何与 Git 进行协作。 8 | -------------------------------------------------------------------------------- /A-git-in-other-environments/images/branch_widget_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/branch_widget_mac.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/branch_widget_win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/branch_widget_win.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/egit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/egit.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/git-bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/git-bash.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/git-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/git-gui.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/github_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/github_mac.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/github_win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/github_win.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/gitk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/gitk.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/posh-git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/posh-git.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/vs-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/vs-1.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/vs-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/vs-2.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/zsh-oh-my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/zsh-oh-my.png -------------------------------------------------------------------------------- /A-git-in-other-environments/images/zsh-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/A-git-in-other-environments/images/zsh-prompt.png -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/bash.adoc: -------------------------------------------------------------------------------- 1 | === Bash 中的 Git 2 | 3 | (((bash)))(((tab completion, bash)))(((shell prompts, bash))) 4 | 如果你是一名 Bash 用户,你可以从中发掘出一些 Shell 的特性,让你在使用 Git 时更加随心所欲。 5 | 实际上 Git 附带了几个 Shell 的插件,但是这些插件并不是默认打开的。 6 | 7 | 首先,你需要从 Git 源代码中获得一份 `contrib/completion/git-completion.bash` 文件的拷贝。 8 | 将这个文件复制到一个相对便捷的目录,例如你的 Home 目录,并且将它的路径添加到 `.bashrc` 中: 9 | 10 | [source,console] 11 | ----- 12 | . ~/git-completion.bash 13 | ----- 14 | 15 | 做完这些之后,请将你当前的目录切换到某一个 Git 仓库,并且输入: 16 | 17 | [source,console] 18 | ---- 19 | $ git chec 20 | ---- 21 | 22 | ……此时 Bash 将会把上面的命令自动补全为 `git checkout`。 23 | 在适当的情况下,这项功能适用于 Git 所有的子命令、命令行参数、以及远程仓库与引用名。 24 | 25 | 这项功能也可以用于你自己定义的提示符(`prompt`),显示当前目录下 Git 仓库的信息。 26 | 根据你的需要,这个信息可以简单或复杂,这里通常有大多数人想要的几个关键信息,比如当前分支信息和当前工作目录的状态信息。 27 | 要添加你自己的提示符(`prompt`),只需从 Git 源版本库复制 `contrib/completion/git-prompt.sh` 文件到你的 Home 目录(或其他便于你访问与管理的目录), 并在 `.bashrc` 里添加这个文件路径,类似于下面这样: 28 | 29 | [source,console] 30 | ----- 31 | . ~/git-prompt.sh 32 | export GIT_PS1_SHOWDIRTYSTATE=1 33 | export PS1='\w$(__git_ps1 " (%s)")\$ ' 34 | ----- 35 | 36 | `\w` 表示打印当前工作目录,`\$` 打印 `$` 部分的提示符(`prompt`),`__git_ps1 " (%s)"` 表示通过格式化参数符(`%s`)调用`git-prompt.sh`脚本中提供的函数。 37 | 因为有了这个自定义提示符,现在你的 `Bash` 提示符(`prompt`)在 Git 仓库的任何子目录中都将显示成这样: 38 | 39 | .自定义的 `bash` 提示符(`prompt`). 40 | image::../images/git-bash.png[自定义的 `bash` 提示符(`prompt`).] 41 | 42 | 这两个脚本都提供了很有帮助的文档;浏览 `git-completion.bash` 和 `git-prompt.sh` 的内容以获得更多信息。 43 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/eclipse.adoc: -------------------------------------------------------------------------------- 1 | === Eclipse 中的 Git 2 | 3 | (((Eclipse))) 4 | Eclipse 附带了一个名为 Egit 的插件,它提供了一个非常完善的 Git 操作接口。 5 | 这个插件可以通过切换到 Git 视图来使用:(Window > Open Perspective > Other…, 然后选择 “Git”)。 6 | 7 | .Eclipse 中 EGit 的界面环境。 8 | image::../images/egit.png[Eclipse 中 EGit 的界面环境。] 9 | 10 | EGit 提供了许多强大的帮助文档,你能通过下面的操作来访问它:单击菜单 Help > Help Contents,然后从内容列表中选择 “EGit Documentation” 节点。 11 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/guis.adoc: -------------------------------------------------------------------------------- 1 | === 图形界面 2 | 3 | (((GUIs)))(((Graphical tools))) 4 | Git 的原生环境是终端。 5 | 在那里,你可以体验到最新的功能,也只有在那里,你才能尽情发挥 Git 的全部能力。 6 | 但是对于某些任务而言,纯文本并不是最佳的选择;有时候你确实需要一个可视化的展示方式,而且有些用户更习惯那种能点击的界面。 7 | 8 | 有一点请注意,不同的界面是为不同的工作流程设计的。 9 | 一些客户端的作者为了支持某种他认为高效的工作流程,经过精心挑选,只显示了 Git 功能的一个子集。 10 | 每种工具都有其特定的目的和意义,从这个角度来看,不能说某种工具比其它的``更好''。 11 | 还有请注意,没有什么事情是图形界面客户端可以做而命令行客户端不能做的;命令行始终是你可以完全操控仓库并发挥出全部力量的地方。 12 | 13 | ==== `gitk` 和 `git-gui` 14 | 15 | (((git commands, gitk)))(((git commands, gui)))(((gitk))) 16 | 在安装 Git 的同时,你也装好了它提供的可视化工具,`gitk` 和 `git-gui`。 17 | 18 | `gitk` 是一个历史记录的图形化查看器。 19 | 你可以把它当作是基于 `git log` 和 `git grep` 命令的一个强大的图形操作界面。 20 | 当你需要查找过去发生的某次记录,或是可视化查看项目历史的时候,你将会用到这个工具。 21 | 22 | 使用 Gitk 的最简单方法就是从命令行打开。 23 | 只需 `cd` 到一个 Git 仓库,然后键入: 24 | 25 | [source,console] 26 | ---- 27 | $ gitk [git log options] 28 | ---- 29 | 30 | Gitk 可以接受很多命令行选项,其中的大部分都直接传给底层的 `git log` 去执行了。 31 | `--all` 可能是这其中最有用的一个, 它告诉 gitk 去尽可能地从 _任何_ 引用查找提交并显示,而不仅仅是从 HEAD。 32 | Gitk 的界面看起来长这样: 33 | 34 | .`gitk` 历史查看器。 35 | image::../images/gitk.png[`gitk` 历史查看器。] 36 | 37 | 这张图看起来就和执行 `git log --graph` 命令的输出差不多;每个点代表一次提交,线代表父子关系,而彩色的方块则用来标示一个个引用。 38 | 黄点表示 HEAD,红点表示尚未提交的本地变动。 39 | 下方的窗口用来显示当前选中的提交的具体信息;评论和补丁显示在左侧,摘要显示在右侧。 40 | 中间则是一组用来搜索历史的控件。 41 | 42 | 与之相比,`git-gui` 则主要是一个用来制作提交的工具。 43 | 打开它的最简单方法也是从命令行启动: 44 | 45 | [source,console] 46 | ----- 47 | $ git gui 48 | ----- 49 | 50 | 它的界面长这个样子: 51 | 52 | .`git-gui` 提交工具。 53 | image::../images/git-gui.png[`git-gui` 提交工具。] 54 | 55 | 左侧是索引区;未暂存的修改显示在上方,已暂存的修改显示在下方。 56 | 你可以通过点击文件名左侧的图标来将该文件在暂存状态与未暂存状态之间切换,你也可以通过选中一个文件名来查看它的详情。 57 | 58 | 右侧窗口的上方以 diff 格式来显示当前选中文件发生了变动的地方。 59 | 你可以通过右击某一区块或行从而将这一区块或行放入暂存区。 60 | 61 | 右侧窗口的下方是写日志和执行操作的地方。 62 | 在文本框中键入日志然后点击 ``提交'' 就和执行 `git commit` 的效果差不多。 63 | 如果你想要修订上一次提交, 可以选中``修订'' 按钮,上次一提交的内容就会显示在 ``暂存区''。 64 | 然后你就可以简单的对修改进行暂存和取消暂存操作,更新提交日志,然后再次点击 ``提交'' 用这个新的提交来覆盖上一次提交。 65 | 66 | `gitk` 和 `git-gui` 就是针对某种任务设计的工具的两个例子。 67 | 它们分别为了不同的目的(即查看历史和制作提交)而进行了精简,略去了用不到的功能。 68 | 69 | 70 | ==== Mac 和 Windows 上的 GitHub 客户端 71 | 72 | (((GitHub for Mac)))(((GitHub for Windows))) 73 | GitHub 发布了两个面向工作流程的 Git 客户端:Windows 版,和 Mac 版。 74 | 它们很好的展示了一个面向工作流程的工具应该是什么样子——专注于提升那些常用的功能及其协作的可用性,而不是实现 Git 的 _所有_ 功能. 75 | 它们看起来长这个样子: 76 | 77 | .GitHub Mac 客户端。 78 | image::../images/github_mac.png[GitHub Mac 客户端。] 79 | 80 | .GitHub Windows 客户端。 81 | image::../images/github_win.png[GitHub Windows 客户端。] 82 | 83 | 我们在设计的时候就努力将二者的外观和操作体验都保持一致,因此本章会把他们当做同一个产品来介绍。 84 | 我们并不会详细地介绍该工具的每一个功能(因为它们本身也有文档),但请快速了解一下 ``变更'' 窗口(你大部分时间都会花在使用该窗口上)的以下几点: 85 | 86 | * 左侧是正在追踪的仓库的列表;通过点击左上方的 ``+'' 图标,你可以添加一个需要追踪的仓库(既可以是通过 clone,也可以从本地添加)。 87 | * 中间是输入-提交区,你可以在这里输入提交日志,以及选择哪些文件需要被提交。 88 | (在 Windows 上,提交历史就显示在这个区域的下方;在 Mac 上,提交历史有一个单独的窗口) 89 | * 右侧是修改查看区,它会告诉你工作目录里哪些东西被修改了(译注:修改模式),或选中的提交里包括了哪些修改(译注:历史模式)。 90 | * 最后需要熟悉的是右上角的 ``Sync'' 按钮,你主要通过这个按钮来进行网络上的交互。 91 | 92 | [NOTE] 93 | ==== 94 | 你不需要注册 GitHub 账号也可以使用这些工具。 95 | 尽管它们是按照 GitHub 推荐的工作流程来设计的,并突出提升了一些 GitHub 的服务体验,但它们可以在任何 Git 仓库上工作良好,也可以通过网络连接到任意 Git 主机。 96 | ==== 97 | 98 | ===== 安装 99 | 100 | GitHub 的 Windows 客户端可以从 https://windows.github.com[] 下载,Mac 客户端可以从 https://mac.github.com[]下载。 101 | 第一次打开软件时,它会引导你进行一系列的首次使用设置,例如设置你的姓名和电子邮件,它还会智能地帮你调整一些常用的默认设置,例如凭证缓存和 CRLF 的处理方式。 102 | 103 | 它们都是``绿色软件''——如果软件打开发现有更新,下载和安装升级包都是在后台完成的。 104 | 为方便起见它们还打包了一份 Git,也就是说你一旦安装好就再也无需劳心升级的事情了。 105 | Windows 的客户端还提供了快捷方式,可以启动装了 Posh-git 插件的 Powershell,在本章的后面一节我们会详细介绍这方面的内容。 106 | 107 | 接下来我们给它设置一些工作仓库。 108 | 客户端会显示你在 GitHub 上有权限操作的仓库的列表,你可以选择一个然后一键克隆。 109 | 如果你本地已经建立了仓库,只需要用鼠标把它从 Finder 或 Windows 资源管理器拖进 GitHub 客户端窗口,就可以把该仓库添加到左侧的仓库列表里面去了。 110 | 111 | ===== 推荐的工作流程 112 | 113 | 安装并配置好以后,你就可以使用 GitHub 客户端来执行一些常见的 Git 任务。 114 | 该工具所推荐的工作流程有时也被叫做 ``GitHub 流''。 115 | 我们在 <<_github_flow>> 一节中对此有详细的介绍,其要点是 (a) 你会提交到一个分支;(b) 你需要经常与远程仓库保持同步。 116 | 117 | 两个平台上的客户端在分支管理上有所不同。 118 | 在 Mac 上,创建分支的按钮在窗口的上方: 119 | 120 | .Mac 上的``创建分支''按钮。 121 | image::../images/branch_widget_mac.png[Mac 上的``创建分支''按钮。] 122 | 123 | 在 Windows 上,你可以通过在分支切换挂件中输入新分支的名称来完成创建: 124 | 125 | .在 Windows 上创建分支。 126 | image::../images/branch_widget_win.png[在 Windows 上创建分支。] 127 | 128 | 分支创建好以后,新建提交就变得非常简单直接了。 129 | 现在工作目录中做一些修改,然后切换到 GitHub 客户端窗口,你所做的修改就会显示在那里。 130 | 输入提交日志,选中那些需要被包含在本次提交中的文件,然后点击 ``提交'' 按钮(也可以在键盘上按 ctrl-enter 或 ⌘-enter)。 131 | 132 | ``同步'' 功能是你在网络上和其它仓库交互的主要途径。 133 | push,fetch,merge,和 rebase 在 Git 内部是一连串独立的操作, 而 GitHub 客户端将这些操作都合并成了单独一个功能。 134 | 你点击同步按钮时实际上会发生如下这些操作: 135 | 136 | . `git pull --rebase`。 137 | 如果上述命令由于存在合并冲突而失败,则会退而执行 `git pull --no-rebase`。 138 | . `git push`。 139 | 140 | 如果你遵循推荐的工作流程,以上就是最常用的一系列命令,因此将它们合并为一个让事情简单了很多。 141 | 142 | ===== 小结 143 | 144 | 这些工具是为其各自针对的工作流程所量身定做的。 145 | 开发者和非开发者可以轻松地在分分钟内就搭建起项目协作环境,它们还内置了其它辅助最佳实践的功能。 146 | 但是,如果你的工作流程有所不同,或者你需要在进行网络操作时有更多的控制,那么建议你考虑一下其它客户端或者使用命令行。 147 | 148 | 149 | ==== 其它图形界面 150 | 151 | 除此之外,还有许许多多其它的图形化 Git 客户端,其中既有单一功能的定制工具,也有试图提供 Git 所有功能的复杂应用。 152 | Git 的官方网站整理了一份时下最流行的客户端的清单 http://git-scm.com/downloads/guis[]。 153 | 在 Git 的维基站点还可以看到一份更全的清单 https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Graphical_Interfaces[]. 154 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/powershell.adoc: -------------------------------------------------------------------------------- 1 | [[_git_powershell]] 2 | === Powershell 中的 Git 3 | 4 | (((powershell)))(((tab completion, powershell)))(((shell prompts, powershell))) 5 | (((posh-git))) 6 | Windows 中的普通命令行终端 (`cmd.exe`) 无法自定义 Git 使用体验,但是如果你正在使用 Powershell,那么你就十分幸运了。 7 | 一个名为 Posh-Git (https://github.com/dahlbyk/posh-git[]) 的扩展包提供了强大的 tab 补全功能, 并针对提示符进行了增强,以帮助你聚焦于你的仓库状态。 8 | 它看起来像: 9 | 10 | .附带了 Posh-Git 扩展包的 Powershell。 11 | image::../images/posh-git.png[附带了 Posh-Git 扩展包的 Powershell。] 12 | 13 | 如果你已经在 Windows 上安装了 GitHub,Posh-Git 也会被安装,你只需要添加以下两行到你的 `profile.ps1` 文件 (文件位于 `C:\Users\\Documents\WindowsPowerShell`): 14 | 15 | [source,powershell] 16 | ----- 17 | . (Resolve-Path "$env:LOCALAPPDATA\GitHub\shell.ps1") 18 | . $env:github_posh_git\profile.example.ps1 19 | ----- 20 | 21 | 如果你没有在 Windows 上安装 GitHub,只需要从 (https://github.com/dahlbyk/posh-git[]) 下载一份 Posh-Git 发行版,并且解压至 `WindowsPowershell` 目录。 22 | 然后以管理员权限打开 Powershell 提示符,并且执行下面的命令: 23 | 24 | [source,powershell] 25 | ----- 26 | > Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm 27 | > cd ~\Documents\WindowsPowerShell\posh-git 28 | > .\install.ps1 29 | ----- 30 | 31 | 它将会向你的 `profile.ps1` 文件添加适当的内容,Posh-Git 将会在下次打开提示符时被启用。 32 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/summary.adoc: -------------------------------------------------------------------------------- 1 | === 总结 2 | 3 | 你已经学会了如何从日常工具中发挥 Git 的强大力量,以及从自己的程序中访问 Git 仓库的方法。 4 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/visualstudio.adoc: -------------------------------------------------------------------------------- 1 | === Visual Studio 中的 Git 2 | 3 | (((Visual Studio))) 4 | 从 Visual Studio 2013 Update 1 版本开始,Visual Studio 用户可以在他们的 IDE 中直接使用内嵌的 Git 客户端。 5 | Visual Studio 集成源代码版本控制特性已经有很长一段时间,但面向的是集中式、文件锁定方式的系统,Git 并不能很好地符合这种工作流程。 6 | Visual Studio 2013 中已经支持 Git,并独立于原有版本管理系统,这使得 Visual Studio 和 Git 能更好地相互适应。 7 | 8 | 想要找到这个特性,在 Visual Studio 中打开一个已经用 Git 管理的项目(或者直接在项目目录中 `git init` ),选择菜单 View > Team Explorer。 9 | 你将看到 "Connect" 视图,大概如下图所示: 10 | 11 | .从 Team Explorer 中连接 Git 仓库。 12 | image::../images/vs-1.png[从 Team Explorer 中连接 Git 仓库。] 13 | 14 | Visual Studio 能够记住所有你打开过的用 Git 管理的项目,它们都在下方的列表中。 15 | 如果没看到你想要的项目,点击 "Add" 按钮,添加项目工作目录的路径。 16 | 双击其中一个本地的 Git 仓库会将你带入 "Home" 视图,大概如 <> 所示。 17 | 这是一个执行 Git 操作的操作中心;当你 _正在编写_ 代码的时候,你可能主要关注 "Changes" 视图,当需要拉取同伴的改动时,你将使用 "Unsynced Commits" 和 "Branches" 视图。 18 | 19 | [[vs_home]] 20 | .Visual Studio 中的 Git 仓库的 “Home” 视图。 21 | image::../images/vs-2.png[Visual Studio 中的 Git 仓库的 “Home” 视图。] 22 | 23 | Visual Studio 现在拥有一套着眼于任务的强大 Git 操作界面。 24 | 它包括线性的历史视图、diff 视图、远程仓库操作命令,以及其它很多功能。 25 | 这个特性的完整文档(放在这里并不合适)请参阅 http://msdn.microsoft.com/en-us/library/hh850437.aspx[] 。 26 | -------------------------------------------------------------------------------- /A-git-in-other-environments/sections/zsh.adoc: -------------------------------------------------------------------------------- 1 | === Zsh 中的 Git 2 | 3 | (((zsh)))(((tab completion, zsh)))(((shell prompts, zsh))) 4 | Git 还为 Zsh 提供了一个 Tab 补全库。 5 | 复制 `contrib/completion/git-completion.zsh` 到你的 home 目录,然后在 `.zshrc` 中 source 即可。 6 | 相对于 Bash,Zsh 的接口更加强大: 7 | 8 | [source,console] 9 | ---- 10 | $ git che 11 | check-attr -- 显示 gitattributes 信息 12 | check-ref-format -- 检查引用名称是否符合规范 13 | checkout -- 从工作区中检出分支或路径 14 | checkout-index -- 从暂存区拷贝文件至工作目录 15 | cherry -- 查找没有被合并至上游的提交 16 | cherry-pick -- 从一些已存在的提交中应用更改 17 | ---- 18 | 19 | 意义不明的 Tab 补全并不仅仅会被列出;它们还会有帮助性的描述,你可以通过不断敲击 Tab 以图形方式浏览补全列表。 20 | 该功能可用于 Git 命令、它们的参数和在仓库中内容的名称(例如 refs 和 remotes),还有文件名和其他所有 Zsh 知道如何去补全的项目。 21 | 22 | 在提示符自定义方面,Zsh 很好地兼容了Bash,并允许你同时使用一个右侧提示符。 23 | 把如下代码添加至你的 `~/.zshrc` 文件中,就可以在右侧显示分支名称: 24 | 25 | [source,console] 26 | ---- 27 | setopt prompt_subst 28 | . ~/git-prompt.sh 29 | export RPROMPT=$'$(__git_ps1 "%s")' 30 | ---- 31 | 32 | 当你的命令行位于一个 Git 仓库目录时,在任何时候,都可以在命令行窗口右侧显示当前分支。 33 | 它看起来像这样: 34 | 35 | .自定义 `zsh` 提示符. 36 | image::../images/zsh-prompt.png[自定义 `zsh` 提示符.] 37 | 38 | Zsh 本身已足够强大,但还有一些专门为它打造的完整框架,使它更加完善。 39 | 其中之一名为 "oh-my-zsh",你可以在 https://github.com/robbyrussell/oh-my-zsh[] 找到它。 40 | oh-my-zsh 的扩展系统包含强大的 Git Tab 补全功能,且许多提示符 "主题" 可以展示版本控制数据。 41 | <> 只是可以其中一个可以通过该系统实现的例子。 42 | 43 | [[oh_my_zsh_git]] 44 | .一个 oh-my-zsh 主题的示例. 45 | image::../images/zsh-oh-my.png[一个 oh-my-zsh 主题的示例.] 46 | -------------------------------------------------------------------------------- /B-embedding-git/1-embedding-git.adoc: -------------------------------------------------------------------------------- 1 | [appendix] 2 | == 将 Git 嵌入你的应用 3 | 4 | 假设你的应用程序的目标人群是开发者,如果它能够被整合进一些源码控制的功能,那真真是极好的。 5 | 甚至对于一个例如文档编辑器之类的不是为开发者而设计的应用程序,它们也可能从版本控制系统中受益,并且 Git 的实现方式在很多情况下都表现得非常出色。 6 | 7 | 如果你想将 Git 整合进你的应用程序的话,一般来说你有三种可能的选择:启动一个 shell 来使用 Git 的命令行工具;使用 Libgit2;或者使用 JGit。 8 | -------------------------------------------------------------------------------- /B-embedding-git/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/1.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/1.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/10.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/10.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/2.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/2.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/3.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/3.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/4.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/4.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/5.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/5.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/6.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/6.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/7.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/7.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/8.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/8.png -------------------------------------------------------------------------------- /B-embedding-git/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/9.pdf -------------------------------------------------------------------------------- /B-embedding-git/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/B-embedding-git/callouts/9.png -------------------------------------------------------------------------------- /B-embedding-git/sections/command-line.adoc: -------------------------------------------------------------------------------- 1 | === 命令行 Git 方式 2 | 3 | 一种方式就是启动一个 shell 进程并在里面使用 Git 的命令行工具来完成任务。 4 | 这种方式看起来很循规蹈矩,但是它的优点也因此而来,就是支持所有的 Git 的特性。 5 | 它也碰巧相当简单,因为几乎所有运行时环境都有一个相对简单的方式来调用一个带有命令行参数的进程。 6 | 然而,这种方式也有一些固有的缺点。 7 | 8 | 一个就是所有的输出都是纯文本格式。 9 | 这意味着你将被迫解析 Git 的有时会改变的输出格式,以随时了解它工作的进度和结果。更糟糕的是,这可能是无效率并且容易出错的。 10 | 11 | 另外一个就是令人捉急的错误修复能力。 12 | 如果一个版本库被莫名其妙地损毁,或者用户使用了一个奇奇怪怪的配置, Git 只会简单地拒绝表现自己的强大能力。 13 | 14 | 还有一个就是进程的管理。 15 | Git 会要求你在一个独立的进程中维护一个 shell 环境,这可能会无谓地增加复杂性。 16 | 试图协调许许多多的类似的进程(尤其是在某些情况下,当不同的进程在访问相同的版本库时)是对你的能力的极大的挑战。 17 | -------------------------------------------------------------------------------- /B-embedding-git/sections/jgit.adoc: -------------------------------------------------------------------------------- 1 | === JGit 2 | 3 | (((jgit)))(((java))) 4 | 如果你想在一个 Java 程序中使用 Git ,有一个功能齐全的 Git 库,那就是 JGit 。 5 | JGit 是一个用 Java 写成的功能相对健全的 Git 的实现,它在 Java 社区中被广泛使用。 6 | JGit 项目由 Eclipse 维护,它的主页在 http://www.eclipse.org/jgit[] 。 7 | 8 | ==== 起步 9 | 10 | 有很多种方式可以让 JGit 连接你的项目,并依靠它去写代码。 11 | 最简单的方式也许就是使用 Maven 。你可以通过在你的 pom.xml 文件里的 `` 标签中增加像下面这样的片段来完成这个整合。 12 | 13 | [source,xml] 14 | ---- 15 | 16 | org.eclipse.jgit 17 | org.eclipse.jgit 18 | 3.5.0.201409260305-r 19 | 20 | ---- 21 | 22 | 在你读到这段文字时 `version` 很可能已经更新了,所以请浏览 http://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit[] 以获取最新的仓库信息。 23 | 当这一步完成之后, Maven 就会自动获取并使用你所需要的 JGit 库。 24 | 25 | 如果你想自己管理二进制的依赖包,那么你可以从 http://www.eclipse.org/jgit/download[] 获得预构建的 JGit 二进制文件。 26 | 你可以像下面这样执行一个命令来将它们构建进你的项目。 27 | 28 | [source,console] 29 | ---- 30 | javac -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App.java 31 | java -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App 32 | ---- 33 | 34 | ==== 底层命令 35 | 36 | JGit 的 API 有两种基本的层次:底层命令和高层命令。 37 | 这个两个术语都来自 Git ,并且 JGit 也被按照相同的方式粗略地划分:高层 API 是一个面向普通用户级别功能的友好的前端(一系列普通用户使用 Git 命令行工具时可能用到的东西),底层 API 则直接作用于低级的仓库对象。 38 | 39 | 大多数 JGit 会话会以 `Repository` 类作为起点,你首先要做的事就是创建一个它的实例。 40 | 对于一个基于文件系统的仓库来说(嗯, JGit 允许其它的存储模型),用 `FileRepositoryBuilder` 完成它。 41 | 42 | [source,java] 43 | ---- 44 | // 创建一个新仓库 45 | Repository newlyCreatedRepo = FileRepositoryBuilder.create( 46 | new File("/tmp/new_repo/.git")); 47 | newlyCreatedRepo.create(); 48 | 49 | // 打开一个存在的仓库 50 | Repository existingRepo = new FileRepositoryBuilder() 51 | .setGitDir(new File("my_repo/.git")) 52 | .build(); 53 | ---- 54 | 55 | 无论你的程序是否知道仓库的确切位置,builder 中的那个流畅的 API 都可以提供给它寻找仓库所需所有信息。 56 | 它可以使用环境变量 (`.readEnvironment()`) ,从工作目录的某处开始并搜索 (`.setWorkTree(…).findGitDir()`) , 或者仅仅只是像上面那样打开一个已知的 `.git` 目录。 57 | 58 | 当你拥有一个 `Repository` 实例后,你就能对它做各种各样的事。 59 | 下面是一个速览: 60 | 61 | [source,java] 62 | ---- 63 | // 获取引用 64 | Ref master = repo.getRef("master"); 65 | 66 | // 获取该引用所指向的对象 67 | ObjectId masterTip = master.getObjectId(); 68 | 69 | // Rev-parse 70 | ObjectId obj = repo.resolve("HEAD^{tree}"); 71 | 72 | // 装载对象原始内容 73 | ObjectLoader loader = repo.open(masterTip); 74 | loader.copyTo(System.out); 75 | 76 | // 创建分支 77 | RefUpdate createBranch1 = repo.updateRef("refs/heads/branch1"); 78 | createBranch1.setNewObjectId(masterTip); 79 | createBranch1.update(); 80 | 81 | // 删除分支 82 | RefUpdate deleteBranch1 = repo.updateRef("refs/heads/branch1"); 83 | deleteBranch1.setForceUpdate(true); 84 | deleteBranch1.delete(); 85 | 86 | // 配置 87 | Config cfg = repo.getConfig(); 88 | String name = cfg.getString("user", null, "name"); 89 | ---- 90 | 91 | 这里完成了一大堆事情,所以我们还是一次理解一段的好。 92 | 93 | 第一行获取一个指向 `master` 引用的指针。 94 | JGit 自动抓取位于 `refs/heads/master` 的 _真正的_ master 引用,并返回一个允许你获取该引用的信息的对象。 95 | 你可以获取它的名字 (`.getName()`) ,或者一个直接引用的目标对象 (`.getObjectId()`) ,或者一个指向该引用的符号指针 (`.getTarget()`) 。 96 | 引用对象也经常被用来表示标签的引用和对象,所以你可以询问某个标签是否被 ``削除'' 了,或者说它指向一个标签对象的(也许很长的)字符串的最终目标。 97 | 98 | 第二行获得以 `master` 引用的目标,它返回一个 ObjectId 实例。 99 | 不管是否存在于一个 Git 对象的数据库,ObjectId 都会代表一个对象的 SHA-1 哈希。 100 | 第三行与此相似,但是它展示了 JGit 如何处理 rev-parse 语法(要了解更多,请看 <<_branch_references>> ),你可以传入任何 Git 了解的对象说明符,然后 JGit 会返回该对象的一个有效的 ObjectId ,或者 `null` 。 101 | 102 | 接下来两行展示了如何装载一个对象的原始内容。 103 | 在这个例子中,我们调用 `ObjectLoader.copyTo()` 直接向标准输出流输出对象的内容,除此之外 ObjectLoader 还带有读取对象的类型和长度并将它以字节数组返回的方法。 104 | 对于一个( `.isLarge()` 返回 `true` 的)大的对象,你可以调用 `.openStream()` 来获得一个类似 InputStream 的对象,它可以在没有一次性将所有数据拉到内存的前提下读取对象的原始数据。 105 | 106 | 接下来几行展现了如何创建一个新的分支。 107 | 我们创建一个 RefUpdate 实例,配置一些参数,然后调用 `.update()` 来确认这个更改。 108 | 删除相同分支的代码就在这行下面。 109 | 记住必须先 `.setForceUpdate(true)` 才能让它工作,否则调用 `.delete()` 只会返回 `REJECTED` ,然后什么都没有发生。 110 | 111 | 最后一个例子展示了如何从 Git 配置文件中获取 `user.name` 的值。 112 | 这个 Config 实例使用我们先前打开的仓库做本地配置,但是它也会自动地检测并读取全局和系统的配置文件。 113 | 114 | 这只是底层 API 的冰山一角,另外还有许多可以使用的方法和类。 115 | 还有一个没有放在这里说明的,就是 JGit 是用异常机制来处理错误的。 116 | JGit API 有时使用标准的 Java 异常(例如 `IOException` ),但是它也提供了大量 JGit 自己定义的异常类型(例如 `NoRemoteRepositoryException`、 `CorruptObjectException` 和 `NoMergeBaseException`)。 117 | 118 | ==== 高层命令 119 | 120 | 底层 API 更加完善,但是有时将它们串起来以实现普通的目的非常困难,例如将一个文件添加到索引,或者创建一个新的提交。 121 | 为了解决这个问题, JGit 提供了一系列高层 API ,使用这些 API 的入口点就是 `Git` 类: 122 | 123 | [source,java] 124 | ---- 125 | Repository repo; 126 | // 构建仓库。。。 127 | Git git = new Git(repo); 128 | ---- 129 | 130 | Git 类有一系列非常好的 _构建器_ 风格的高层方法,它可以用来构造一些复杂的行为。 131 | 我们来看一个例子——做一件类似 `git ls-remote` 的事。 132 | 133 | [source,java] 134 | ---- 135 | CredentialsProvider cp = new UsernamePasswordCredentialsProvider("username", "p4ssw0rd"); 136 | Collection remoteRefs = git.lsRemote() 137 | .setCredentialsProvider(cp) 138 | .setRemote("origin") 139 | .setTags(true) 140 | .setHeads(false) 141 | .call(); 142 | for (Ref ref : remoteRefs) { 143 | System.out.println(ref.getName() + " -> " + ref.getObjectId().name()); 144 | } 145 | ---- 146 | 147 | 这是一个 Git 类的公共样式,这个方法返回一个可以让你串连若干方法调用来设置参数的命令对象,当你调用 `.call()` 时它们就会被执行。 148 | 在这情况下,我们只是请求了 `origin` 远程的标签,而不是头部。 149 | 还要注意用于验证的 `CredentialsProvider` 对象的使用。 150 | 151 | 在 Git 类中还可以使用许多其它的命令,包括但不限于 `add`、`blame`、`commit`、`clean`、`push`、`rebase`、`revert` 和 `reset`。 152 | 153 | ==== 拓展阅读 154 | 155 | 这只是 JGit 的全部能力的冰山一角。 156 | 如果你对这有兴趣并且想深入学习,在下面可以找到一些信息和灵感。 157 | 158 | * JGit API 在线官方文档: http://download.eclipse.org/jgit/docs/latest/apidocs[] 。 159 | 这是基本的 Javadoc ,所以你也可以在你最喜欢的 JVM IDE 上将它们安装它们到本地。 160 | * JGit Cookbook : https://github.com/centic9/jgit-cookbook[] 拥有许多如何利用 JGit 实现特定任务的例子。 161 | * http://stackoverflow.com/questions/6861881[] 指出了几个好的资源。 162 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | [[_bingohuang]] 2 | 3 | = Pro Git,第二版,简体中文 4 | 5 | * _作为Git官方推荐书籍,《Pro Git》值得Git初学者和爱好者认真阅读一遍。_ 6 | 7 | * _本人很喜欢 https://www.gitbook.com/@bingohuang[GitBook] 的阅读书籍模式,喜爱开源共享。_ 8 | _当前GitBook网站上只有《Pro Git》第一版,故我将《Pro Git》第二版(简体中文版)整理迁移至此,方便大家统一阅读学习。_ 9 | 10 | * https://www.gitbook.com/book/bingohuang/progit2/details[_《Pro Git》第二版书籍@GitBook_] 11 | 12 | * https://github.com/bingoHuang/progit2-gitbook[_《Pro Git》第二版源码@Github_] :欢迎做 `fork - 修改 - pull request` 13 | 14 | * _GitBook生成的 `PDF` 格式书籍,对中文字体支持不好,这边上传完美 `PDF`版本至百度网盘中 ,方便大家本地下载查看。【感谢 `李志霞` 同学的建议和文件】_ 15 | 16 | ** http://pan.baidu.com/s/1gdV3fsJ[_百度网盘-《Pro Git 第二版 简体中文》_] 17 | 18 | * _《Pro Git》第二版原书格式是 `AsciiDoc` ,和常用的 `Markdown` 格式略有不同,还好 `GitBook 2.0.0` 之后已支持,方便我整理到 https://www.gitbook.com/@bingohuang[GitBook] 中,其中 https://help.gitbook.com/format/asciidoc.html[AsciiDoc帮助文档点此] 。_ 19 | 20 | * _感谢原著作者及翻译者:_ http://git-scm.com/book/zh/v2[_书籍官网地址_] 21 | 22 | * _我的邮箱[bingo727@gmail.com],欢迎一起交流~_ 23 | 24 | == 当前完成进度(更新完成): 25 | 26 | . 前言 27 | . 第一章:起步 28 | . 第二章:Git基础 29 | . 第三章:Git分支 30 | . 第四章:服务器上的 Git 31 | . 第五章:分布式 Git 32 | . 第六章:GitHub 33 | . 第七章:Git 工具 34 | . 第八章:自定义 Git 35 | . 第九章:Git 与其他系统 36 | . 第十章:Git 内部原理 37 | . 附录A:其它环境中的 Git 38 | . 附录B:将 Git 嵌入你的应用 39 | . 附录C:Git 命令 40 | . 贡献者 41 | . 本书遗留问题: 42 | .. 书籍内部链接不能跳转,GitBook对Asciidoc支持的还不够完善 43 | .. GitBook下载的PDF文件中文支持不好,可从上文的链接中下载打包好的PDF文件。 44 | 45 | = 原书前言 46 | 欢迎阅读 Pro Git 第二版。 47 | 48 | 你可以在以下地址找到本书的在线版本: http://git-scm.com/book 49 | 50 | 与第一版类似,Pro Git 第二版以知识共享协议开源。 51 | 52 | 自第一版开源以来,许多事情都发生了变化。 53 | 其一,我们将本书的文本由 Markdown 迁移至 Asciidoc。 54 | 同时,我们还开始使用 O'Reilly 的 https://atlas.oreilly.com[Atlas平台] 持续构建生成本书,因此,所有主要格式在每种语言都是可用的。 55 | 56 | = 原书序言 57 | 58 | [preface] 59 | == Scott Chacon 序 60 | 61 | 欢迎来到 Pro Git 第二版。 62 | 第一版出版到现在已经过去了四年。 63 | 到今天,Git 虽然出现了许多改变,但是还有很多重要的事情一如昨日。 64 | 因为 Git 核心团队对保持向后兼容性异常固执,所以直到今天大多数核心命令与概念依然有效,但是围绕 Git 的社区还是有一些重大的增加与改变。 65 | 本书的第二版就是为了更新书籍并讲解那些改动以使其对新用户更有帮助。 66 | 67 | 当我写第一版时,Git 对于超级黑客来说还是一个相对难用,只能勉强接受的工具。 68 | 它开始在特定的社区中快速发展,但是还没有达到像今天一样无处不在的地步。 69 | 自那时起,几乎每一个开源社区都采用了它。 70 | Git 在 Windows 上取得了难以置信的进步,包括所有平台的图形用户界面对它的支持、IDE 的支持,以及商业使用的爆炸式发展。 71 | 四年前的 Pro Git 对此一无所知。 72 | 新版本的主要目标之一就是涉及 Git 社区中那些所有新的前沿领域。 73 | 74 | 使用 Git 的开源社区也呈现出爆炸式的发展。 75 | 大概在五年前吧,我坐下来写这本书时(写完第一个版本花了我不少时间),我开始在一个知名度极小的开发 Git 托管网站的公司工作,这家公司就是 GitHub。 76 | 本书出版时大概有几千人在使用 GitHub 网站,而为其工作的只有我们四个人。 77 | 在我写这篇介绍时,GitHub 宣布我们托管了 1000 万个项目、拥有大概 500 万注册开发者账户与大概 230 名员工。 78 | 爱它也好,恨它也罢,当我坐下来写第一版时,GitHub 以一种意想不到的方式猛烈地改变了一大批开源社区。 79 | 80 | 我在 Pro Git 的原始版本中写了一节我并不是很满意的内容,是作为和提供 Git 托管服务相关的例子的 GitHub。 81 | 我在书里写的东西本质上都是和社区有关的,但是又不得不讨论到我的公司,这点我不喜欢。 82 | 同时我还不喜欢那个兴趣的冲突,GitHub 在 Git 社区中的重要性是无法避免的。 83 | 我已经决定将本书的那部分转变为深度介绍 GitHub 是什么以及如何高效地使用它,而不再是作为一个 Git 托管的例子。 84 | 如果你正学习如何使用 Git,那么了解如何使用 GitHub 将会帮助你加入到一个巨大的社区中。不论你决定为自己的代码使用哪一个 Git 托管服务,这都很有价值。 85 | 86 | 自从上次出版以来另一个重大变革是 Git 网络传输 HTTP 协议的开发与崛起。书中的大多数例子都已经从 SSH 切换到 HTTP,因为它更简单。 87 | 88 | 在过去这几年看到 Git 从一个相对无名的版本管理系统成长为商业与开源版本管理的事实标准是令人吃惊的。我很高兴 Pro Git 做得很好并已经成为市场上几本既成功又完全开源的技术书籍之一。 89 | 90 | 我希望你能享受这个升级版的 Pro Git。 91 | 92 | [preface] 93 | == Ben Straub 序 94 | 95 | 本书的第一版就是将我与 Git 结下不解之缘的原因。书中采用的是我引进的做软件的风格,这种风格比我之前看到的任何事情都要自然。那时我已经做了好几年开发者了,但是这本书将我指引到一条更加精彩的道路上。 96 | 97 | 几年之后的现在,我是 Git 的一个主要实现的贡献者,我在最大的 Git 托管公司工作,我已经环游世界教人们使用 Git。当 Scott 问我是否有兴趣在第二版上工作时,我甚至连想都没想就答应了。 98 | 99 | 能在这本书上工作是一份巨大的快乐与荣耀。我希望它能像帮助我一样帮助你。 100 | 101 | 102 | [preface] 103 | == 献辞 104 | 105 | _致我的妻子,Becky,没有她的话这段冒险不会开始。— Ben_ 106 | 107 | _谨以此书献给我的家人。 108 | 给这些年一直支持着我的妻子 Jessica 和女儿 Josephine, 109 | 还有那些在我风烛残年之时还能支持我的人。— Scott_ 110 | 111 | [preface] 112 | = 原书引言 113 | 114 | 你将花费你生命中的若干小时来阅读有关 Git 的相关内容。让我们用几分钟时间来介绍下我们将给你讲解的内容。 115 | 下面是本书正文十章和附录三章的快速总结。 116 | 117 | *第一章*,我们将介绍版本控制系统(VCSs)和 Git 的基本概念——不涉及技术内容,仅仅是什么是 Git,为什么它会成为 VCSs 大家庭中的一员,它与其它 VCSs 的区别,以及为什么那么多人都在使用 Git。然后,我们将介绍如何下载 Git 以及如果你的系统没有安装 Git,如何为第一次运行做准备。 118 | 119 | *第二章*,我们将阐述 Git 的基本使用——包含你在使用 Git 时可能遇到的 80% 的情形。通过阅读本章,你应该能够克隆仓库、查看项目历史、修改文件和贡献更改。如果本书在此刻自燃,你应该已经能够使用已经学到的漂亮有用的 Git 知识获取到另外一份拷贝。 120 | 121 | *第三章*, 关注于 Git 的分支模型。分支模型通常被认为是 Git 的杀手级特性。这里,你将学习到究竟是什么让 Git与众不同。学习完本章,你可能需要一段时间来思考,在 Git 分支成为你的生活的一部分之前,你到底是如何生活的。 122 | 123 | *第四章*, 关注于服务器端的 Git。本章面向那些希望在你自己的组织或个人服务器搭建用于合作的 Git 的读者。如果你希望让别人处理这些事务,我们也会探讨一些托管选项。 124 | 125 | *第五章*, 将阐述多种分布式工作流的细节,以及如何使用 Git 实现它们。学习完本章,你应该能够在多个远程仓库之间游刃有余,通过电子邮件使用 Git,熟练地处理多个远程分支和合作者贡献的补丁。 126 | 127 | *第六章*, 介绍 GitHub 托管服务以及深层次的工具。我们将涵盖注册与账户管理,创建和使用 Git 仓库,贡献项目的普通工作流以及接受他人的贡献,GitHub 的可编程接口和那些能够让你的生活变得更简单的小技巧。 128 | 129 | *第七章*, 关于 Git 的高级命令。你将学习到一些高级主题,诸如掌握可怕的“reset”命令,使用二分搜索识别错误,编辑历史,细节版本选择等等。本章的介绍将丰富你的 Git 知识,让你成为一个真正的大师。 130 | 131 | *第八章*, 关于 Git 环境的自定义配置,包括设置用于增强或促进自定义策略的钩子脚本以及按照你所需要的方式进行工作的环境配置。我们还会介绍构建你自己的脚本集,以增强自定义提交策略。 132 | 133 | *第九章*, 对比 Git 和其它 VCSs,包括在 Subversion(SVN)的世界使用 Git 以及从其它 VCSs 迁移到 Git。很多组织仍在使用 SVN,并且也没有计划改变,此时,你将了解到 Git 不可思议的能力——本章将展示,在你不得不使用 SVN 服务器的时候如何协同合作。我们还将介绍如何从不同系统导入项目,以便你能够全身心投入 Git 的怀抱。 134 | 135 | *第十章*, 深入 Git 阴暗而漂亮的实现细节。现在,你已经知道所有有关 Git 的知识,能够熟练运用 Git 的强大优雅的功能。接下来,你可以继续学习 Git 如何存储对象、Git 的对象模型是怎样的、打包文件的细节、服务器协议等更多知识。本书自始至终都将引用本章的内容,以便你能够在当时就可以深入了解。但是,如果你像我们一样希望深入学习技术细节,你可能想先阅读第十章。我们将选择权交给你。 136 | 137 | 在 *附录 A*,我们学习多个在特定环境中使用 Git 的实例。我们涵盖多个你可能会使用 Git 的多个 GUI 和 IDE 编程环境,这些都可以由你自己选择。如果你想在 shell、Visual Studio 或 Eclipse 中使用 Git,请阅读本章。 138 | 139 | 在 *附录 B*,我们探讨通过类似 libgit2 和 JGit 的工具编写 Git 脚本、扩展 Git。如果你对编写复杂、快速的自定义工具感兴趣,需要了解 Git 的底层访问,本章就是你所需要了解的。 140 | 141 | 最后在 *附录 C*,我们一次性浏览 Git 的所有主要命令,复习在本书中介绍的内容,回忆我们能够使用这些命令做什么。如果你需要知道本书中我们使用了哪些特定 Git 命令,你可以在这里查阅。 142 | 143 | 下面让我们开始学习吧! 144 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /contributors.adoc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == 贡献者 3 | 4 | 因为这是一本开源书籍,这几年我们获得了捐赠的若干勘误表与内容修改。下面是将 ProGit 英文版作为开源项目贡献的所有人员。感谢你们帮助将这本书变成对每一个人都更好的书。 5 | 6 | [source] 7 | ---- 8 | 2 Aaron Schumacher 9 | 4 Aggelos Orfanakos 10 | 4 Alec Clews 11 | 1 Alex Moundalexis 12 | 2 Alexander Harkness 13 | 1 Alexander Kahn 14 | 1 Andrew McCarthy 15 | 1 AntonioK 16 | 1 Benjamin Bergman 17 | 1 Brennon Bortz 18 | 2 Brian P O'Rourke 19 | 1 Bryan Goines 20 | 1 Cameron Wright 21 | 1 Chris Down 22 | 1 Christian Kluge 23 | 1 Christoph Korn 24 | 2 Ciro Santilli 25 | 2 Cor 26 | 1 Dan Croak 27 | 1 Dan Johnson 28 | 1 Daniel Kay 29 | 2 Daniel Rosen 30 | 1 DanielWeber 31 | 1 Dave Dash 32 | 10 Davide Fiorentino lo Regio 33 | 2 Dilip M 34 | 1 Dimitar Bonev 35 | 1 Emmanuel Trillaud 36 | 1 Eric-Paul Lecluse 37 | 1 Eugene Serkin 38 | 1 Fernando Dobladez 39 | 2 Gordon McCreight 40 | 1 Helmut K. C. Tessarek 41 | 31 Igor Murzov 42 | 1 Ilya Kuznetsov 43 | 1 Jason St. John 44 | 1 Jay Taggart 45 | 1 Jean Jordaan 46 | 51 Jean-Noël Avila 47 | 1 Jean-Noël Rouvignac 48 | 1 Jed Hartman 49 | 1 Jeffrey Forman 50 | 1 John DeStefano 51 | 1 Junior 52 | 1 Kieran Spear 53 | 1 Larry Shatzer, Jr 54 | 1 Linquize 55 | 1 Markus 56 | 7 Matt Deacalion Stevens 57 | 1 Matthew McCullough 58 | 1 Matthieu Moy 59 | 1 Max F. Albrecht 60 | 1 Michael Schneider 61 | 8 Mike D. Smith 62 | 1 Mike Limansky 63 | 1 Olivier Trichet 64 | 1 Ondrej Novy 65 | 6 Ori Avtalion 66 | 1 Paul Baumgart 67 | 1 Peter Vojtek 68 | 1 Philipp Kempgen 69 | 2 Philippe Lhoste 70 | 1 PowerKiKi 71 | 1 Radek Simko 72 | 1 Rasmus Abrahamsen 73 | 1 Reinhard Holler 74 | 1 Ross Light 75 | 1 Ryuichi Okumura 76 | 1 Sebastian Wiesinger 77 | 1 Severyn Kozak 78 | 1 Shane 79 | 2 Shannen 80 | 8 Sitaram Chamarty 81 | 5 Soon Van 82 | 4 Sven Axelsson 83 | 2 Tim Court 84 | 1 Tuomas Suutari 85 | 1 Vlad Gorodetsky 86 | 3 W. Trevor King 87 | 1 Wyatt Carss 88 | 1 Włodzimierz Gajda 89 | 1 Xue Fuqiao 90 | 1 Yue Lin Ho 91 | 2 adelcambre 92 | 1 anaran 93 | 1 bdukes 94 | 1 burningTyger 95 | 1 cor 96 | 1 iosias 97 | 7 nicesw123 98 | 1 onovy 99 | 2 pcasaretto 100 | 1 sampablokuper 101 | ---- 102 | 103 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/cover.jpg -------------------------------------------------------------------------------- /cover_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingohuang/progit2-gitbook/b646afac2c58aff792506a7487445ef5933a5954/cover_small.jpg -------------------------------------------------------------------------------- /introduction.adoc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == 引言 3 | 4 | 你将花费你生命中的若干小时来阅读有关 Git 的相关内容。让我们用几分钟时间来介绍下我们将给你讲解的内容。 5 | 下面是本书正文十章和附录三章的快速总结。 6 | 7 | 在*第一章*,我们将介绍版本控制系统(VCSs)和 Git 的基本概念——不涉及技术内容,仅仅是什么是 Git, 8 | 为什么它会成为 VCSs 大家庭中的一员,它与其它 VCSs 的区别,以及为什么那么多人都在使用 Git。然后,我们将 9 | 介绍如何下载 Git 以及如果你的系统没有安装 Git,如何为第一次运行做准备。 10 | 11 | 在*第二章*,我们将阐述 Git 的基本使用——包含你在使用 Git 时可能遇到的 80% 的情形。通过阅读本章,你应该 12 | 能够克隆仓库、查看项目历史、修改文件和贡献更改。如果本书在此刻自燃,你应该已经能够使用已经学到的漂亮 13 | 有用的 Git 知识获取到另外一份拷贝。 14 | 15 | *第三章*关注于 Git 的分支模型。分支模型通常被认为是 Git 的杀手级特性。这里,你将学习到究竟是什么让 Git 16 | 与众不同。学习完本章,你可能需要一段时间来思考,在 Git 分支成为你的生活的一部分之前,你到底是如何生活的。 17 | 18 | *第三章*关注于服务器端的 Git。本章面向那些希望在你自己的组织或个人服务器搭建用于合作的 Git 的读者。 19 | 如果你希望让别人处理这些事务,我们也会探讨一些托管选项。 20 | 21 | *第五章*将阐述多种分布式工作流的细节,以及如何使用 Git 实现它们。学习完本章,你应该能够在多个远程仓库 22 | 之间游刃有余,通过电子邮件使用 Git,熟练地处理多个远程分支和合作者贡献的补丁。 23 | 24 | *第六章*介绍 GitHub 托管服务以及深层次的工具。我们将涵盖注册与账户管理,创建和使用 Git 仓库,贡献项目的 25 | 普通工作流以及接受他人的贡献,GitHub 的可编程接口和那些能够让你的生活变得更简单的小技巧。 26 | 27 | *第七章*关于 Git 的高级命令。你将学习到一些高级主题,诸如掌握可怕的“reset”命令,使用二分搜索识别错误,编辑 28 | 历史,细节版本选择等等。本章的介绍将丰富你的 Git 知识,让你成为一个真正的大师。 29 | 30 | *第八章*关于 Git 环境的自定义配置,包括设置用于增强或促进自定义策略的钩子脚本以及按照你所需要的方式进行 31 | 工作的环境配置。我们还会介绍构建你自己的脚本集,以增强自定义提交策略。 32 | 33 | *第九章*对比 Git 和其它 VCSs,包括在 Subversion(SVN)的世界使用 Git 以及从其它 VCSs 迁移到 Git。很多组织 34 | 仍在使用 SVN,并且也没有计划改变,此时,你将了解到 Git 不可思议的能力——本章将展示,在你不得不使用 SVN 服务器 35 | 的时候如何协同合作。我们还将介绍如何从不同系统导入项目,以便你能够全身心投入 Git 的怀抱。 36 | 37 | *第十章*深入 Git 阴暗而漂亮的实现细节。现在,你已经知道所有有关 Git 的知识,能够熟练运用 Git 的强大优雅的功能。 38 | 接下来,你可以继续学习 Git 如何存储对象、Git 的对象模型是怎样的、打包文件的细节、服务器协议等更多知识。 39 | 本书自始至终都将引用本章的内容,以便你能够在当时就可以深入了解。但是,如果你像我们一样希望深入学习技术细节, 40 | 你可能想先阅读第十章。我们将选择权交给你。 41 | 42 | 在*附录 A*,我们学习多个在特定环境中使用 Git 的实例。我们涵盖多个你可能会使用 Git 的多个 GUI 和 IDE 编程环境, 43 | 这些都可以由你自己选择。如果你想在 shell、Visual Studio 或 Eclipse 中使用 Git,请阅读本章。 44 | 45 | 在*附录 B*,我们探讨通过类似 libgit2 和 JGit 的工具编写 Git 脚本、扩展 Git。如果你对编写复杂、快速的自定义工具感兴趣, 46 | 需要了解 Git 的底层访问,本章就是你所需要了解的。 47 | 48 | 最后在*附录 C*,我们一次性浏览 Git 的所有主要命令,复习在本书中介绍的内容,回忆我们能够使用这些命令做什么。 49 | 如果你需要知道本书中我们使用了哪些特定 Git 命令,你可以在这里查阅。 50 | 51 | 下面让我们开始。 52 | -------------------------------------------------------------------------------- /preface.adoc: -------------------------------------------------------------------------------- 1 | Pro Git 2 | ======= 3 | :doctype: book 4 | :docinfo: 5 | :toc: 6 | :toclevels: 2 7 | 8 | [preface] 9 | == Scott Chacon 序 10 | 11 | 欢迎来到 Pro Git 第二版。 12 | 第一版出版到现在已经过去了四年。 13 | 到今天,Git 虽然出现了许多改变,但是还有很多重要的事情一如昨日。 14 | 因为 Git 核心团队对保持向后兼容性异常固执,所以直到今天大多数核心命令与概念依然有效,但是围绕 Git 的社区还是有一些重大的增加与改变。 15 | 本书的第二版就是为了更新书籍并讲解那些改动以使其对新用户更有帮助。 16 | 17 | 当我写第一版时,Git 对于超级黑客来说还是一个相对难用,只能勉强接受的工具。 18 | 它开始在特定的社区中快速发展,但是还没有达到像今天一样无处不在的地步。 19 | 自那时起,几乎每一个开源社区都采用了它。 20 | Git 在 Windows 上取得了难以置信的进步,包括所有平台的图形用户界面对它的支持、IDE 的支持,以及商业使用的爆炸式发展。 21 | 四年前的 Pro Git 对此一无所知。 22 | 新版本的主要目标之一就是涉及 Git 社区中那些所有新的前沿领域。 23 | 24 | 使用 Git 的开源社区也呈现出爆炸式的发展。 25 | 大概在五年前吧,我坐下来写这本书时(写完第一个版本花了我不少时间),我开始在一个知名度极小的开发 Git 托管网站的公司工作,这家公司就是 GitHub。 26 | 本书出版时大概有几千人在使用 GitHub 网站,而为其工作的只有我们四个人。 27 | 在我写这篇介绍时,GitHub 宣布我们托管了 1000 万个项目、拥有大概 500 万注册开发者账户与大概 230 名员工。 28 | 爱它也好,恨它也罢,当我坐下来写第一版时,GitHub 以一种意想不到的方式猛烈地改变了一大批开源社区。 29 | 30 | 我在 Pro Git 的原始版本中写了一节我并不是很满意的内容,是作为和提供 Git 托管服务相关的例子的 GitHub。 31 | 我在书里写的东西本质上都是和社区有关的,但是又不得不讨论到我的公司,这点我不喜欢。 32 | 同时我还不喜欢那个兴趣的冲突,GitHub 在 Git 社区中的重要性是无法避免的。 33 | 我已经决定将本书的那部分转变为深度介绍 GitHub 是什么以及如何高效地使用它,而不再是作为一个 Git 托管的例子。 34 | 如果你正学习如何使用 Git,那么了解如何使用 GitHub 将会帮助你加入到一个巨大的社区中。不论你决定为自己的代码使用哪一个 Git 托管服务,这都很有价值。 35 | 36 | 自从上次出版以来另一个重大变革是 Git 网络传输 HTTP 协议的开发与崛起。书中的大多数例子都已经从 SSH 切换到 HTTP,因为它更简单。 37 | 38 | 在过去这几年看到 Git 从一个相对无名的版本管理系统成长为商业与开源版本管理的事实标准是令人吃惊的。我很高兴 Pro Git 做得很好并已经成为市场上几本既成功又完全开源的技术书籍之一。 39 | 40 | 我希望你能享受这个升级版的 Pro Git。 41 | 42 | [preface] 43 | == Ben Straub 序 44 | 45 | 本书的第一版就是将我与 Git 结下不解之缘的原因。书中采用的是我引进的做软件的风格,这种风格比我之前看到的任何事情都要自然。那时我已经做了好几年开发者了,但是这本书将我指引到一条更加精彩的道路上。 46 | 47 | 几年之后的现在,我是 Git 的一个主要实现的贡献者,我在最大的 Git 托管公司工作,我已经环游世界教人们使用 Git。当 Scott 问我是否有兴趣在第二版上工作时,我甚至连想都没想就答应了。 48 | 49 | 能在这本书上工作是一份巨大的快乐与荣耀。我希望它能像帮助我一样帮助你。 50 | 51 | 52 | [preface] 53 | == 献辞 54 | 55 | _致我的妻子,Becky,没有她的话这段冒险不会开始。— Ben_ 56 | 57 | _谨以此书献给我的家人。 58 | 给这些年一直支持着我的妻子 Jessica 和女儿 Josephine, 59 | 还有那些在我风烛残年之时还能支持我的人。— Scott_ 60 | --------------------------------------------------------------------------------