├── book ├── index.asc ├── toc.asc ├── license.asc ├── cover.png ├── cover.html ├── 06-github │ ├── 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 │ │ ├── 4-managing-organization.asc │ │ └── 1-setting-up-account.asc ├── 07-git-tools │ ├── callouts │ │ ├── 1.pdf │ │ ├── 1.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 │ │ ├── 10.pdf │ │ └── 10.png │ ├── git-credential-read-only │ └── sections │ │ └── subtree-merges.asc ├── B-embedding-git │ ├── callouts │ │ ├── 1.pdf │ │ ├── 1.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 │ │ ├── 10.pdf │ │ └── 10.png │ └── sections │ │ ├── command-line.asc │ │ ├── dulwich.asc │ │ └── go-git.asc ├── dedication.asc ├── preface_ben.asc ├── A-git-in-other-environments │ └── sections │ │ ├── visualstudio.asc │ │ ├── jetbrainsides.asc │ │ ├── sublimetext.asc │ │ ├── visualstudiocode.asc │ │ ├── bash.asc │ │ ├── zsh.asc │ │ └── powershell.asc ├── 04-git-server │ └── sections │ │ ├── hosted.asc │ │ ├── git-daemon.asc │ │ ├── generating-ssh-key.asc │ │ ├── gitweb.asc │ │ ├── smart-http.asc │ │ └── git-on-a-server.asc ├── 01-introduction │ └── sections │ │ ├── command-line.asc │ │ ├── history.asc │ │ ├── help.asc │ │ ├── about-version-control.asc │ │ ├── what-is-git.asc │ │ └── first-time-setup.asc ├── preface_schacon.asc ├── 10-git-internals │ └── sections │ │ ├── plumbing-porcelain.asc │ │ └── refspec.asc ├── 02-git-basics │ └── sections │ │ ├── aliases.asc │ │ ├── getting-a-repository.asc │ │ └── undoing.asc ├── 03-git-branching │ └── sections │ │ ├── branch-management.asc │ │ └── workflows.asc ├── introduction.asc ├── 05-distributed-git │ └── sections │ │ └── distributed-workflows.asc └── 09-git-and-other-scms │ └── sections │ ├── import-p4.asc │ └── import-svn.asc ├── index.asc ├── Pro.ico ├── .mailmap ├── 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 ├── egit.png ├── gitk.png ├── jb.png ├── vs-1.png ├── vs-2.png ├── 2fa-1.png ├── areas.png ├── clean.png ├── deltas.png ├── emoji.png ├── hubot.png ├── local.png ├── neworg.png ├── signup.png ├── smudge.png ├── bitnami.png ├── git-bash.png ├── git-gui.png ├── lifecycle.png ├── new-repo.png ├── newrepo.png ├── p4merge.png ├── posh-git.png ├── replace1.png ├── replace2.png ├── replace3.png ├── replace4.png ├── replace5.png ├── rerere1.png ├── rerere2.png ├── rerere3.png ├── reset-ex1.png ├── reset-ex2.png ├── reset-ex3.png ├── reset-ex4.png ├── reset-ex5.png ├── reset-ex6.png ├── snapshots.png ├── ssh-keys.png ├── zsh-oh-my.png ├── avatar-crop.png ├── blink-02-pr.png ├── centralized.png ├── distributed.png ├── double-dot.png ├── forkbutton.png ├── github_mac.png ├── github_win.png ├── gitlab-menu.png ├── newrepoform.png ├── pr-01-fail.png ├── rebasing-1.png ├── rebasing-2.png ├── reset-hard.png ├── reset-mixed.png ├── reset-path1.png ├── reset-path2.png ├── reset-path3.png ├── reset-soft.png ├── reset-start.png ├── zsh-prompt.png ├── advance-master.png ├── basic-rebase-1.png ├── basic-rebase-2.png ├── basic-rebase-3.png ├── basic-rebase-4.png ├── blink-01-start.png ├── blink-04-email.png ├── blink-06-final.png ├── collaborators.png ├── data-model-1.png ├── data-model-2.png ├── data-model-3.png ├── data-model-4.png ├── email-settings.png ├── git-diff-check.png ├── git-instaweb.png ├── gitlab-groups.png ├── gitlab-users.png ├── head-to-master.png ├── large-merges-1.png ├── large-merges-2.png ├── lr-branches-1.png ├── lr-branches-2.png ├── maint-01-email.png ├── maint-02-merge.png ├── managed-team-1.png ├── managed-team-2.png ├── managed-team-3.png ├── notifications.png ├── orgs-01-page.png ├── orgs-02-teams.png ├── orgs-03-audit.png ├── public-small-1.png ├── public-small-2.png ├── public-small-3.png ├── reset-checkout.png ├── reset-workflow.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 ├── two-branches.png ├── your-profile.png ├── account-settings.png ├── advance-testing.png ├── basic-merging-1.png ├── basic-merging-2.png ├── checkout-master.png ├── commit-and-tree.png ├── git-fusion-boot.png ├── gitlab-broadcast.png ├── head-to-testing.png ├── maint-04-target.png ├── maint-09-contrib.png ├── pr-02-merge-fix.png ├── reposettingslink.png ├── reset-squash-r1.png ├── reset-squash-r2.png ├── reset-squash-r3.png ├── small-team-flow.png ├── topic-branches-1.png ├── topic-branches-2.png ├── undomerge-reset.png ├── undomerge-revert.png ├── undomerge-start.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 ├── benevolent-dictator.png ├── blink-04-pr-comment.png ├── branch-and-history.png ├── branch_widget_mac.png ├── branch_widget_win.png ├── commits-and-parents.png ├── git-osx-installer.png ├── integration-manager.png ├── maint-03-email-resp.png ├── maint-05-mentions.png ├── maint-11-transfer.png ├── managed-team-flow.png ├── markdown-01-example.png ├── markdown-02-tasks.png ├── markdown-05-quote.png ├── markdown-07-emoji.png ├── mentions-01-syntax.png ├── mentions-02-render.png ├── mentions-03-closed.png ├── merging-workflows-1.png ├── merging-workflows-2.png ├── merging-workflows-3.png ├── merging-workflows-4.png ├── merging-workflows-5.png ├── remote-branches-1.png ├── remote-branches-2.png ├── remote-branches-3.png ├── remote-branches-4.png ├── remote-branches-5.png ├── scripting-07-status.png ├── undomerge-revert2.png ├── undomerge-revert3.png ├── centralized_workflow.png ├── interesting-rebase-1.png ├── interesting-rebase-2.png ├── interesting-rebase-3.png ├── interesting-rebase-4.png ├── interesting-rebase-5.png ├── maint-06-unsubscribe.png ├── markdown-08-drag-drop.png ├── merging-workflows-4 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 ├── scripting-01-services.png ├── scripting-03-webhook.png ├── scripting-06-comment.png ├── blink-05-general-comment.png ├── blink-pull-request-open.png ├── maint-07-notifications.png ├── maint-10-default-branch.png ├── markdown-03-task-summary.png ├── markdown-04-fenced-code.png ├── blink-03-pull-request-open.png ├── git-fusion-perforce-graph.png ├── markdown-06-emoji-complete.png ├── scripting-02-email-service.png ├── scripting-04-webhook-debug.png ├── scripting-05-access-token.png ├── blink-pull-request-open copy.png ├── maint-08-notifications-page.png ├── basic-branching-1.svg ├── basic-branching-2.svg ├── local.svg ├── two-branches.svg ├── head-to-testing.svg ├── rerere1.svg ├── basic-branching-3.svg ├── head-to-master.svg └── advance-testing.svg ├── diagram-source └── progit.sketch ├── LICENSE.asc ├── .gitignore ├── .tgitconfig ├── .dependabot └── config.yml ├── .github ├── workflows │ ├── pr-build.yml │ └── release-on-merge.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── theme ├── epub │ ├── layout.html │ └── epub.xsl ├── html │ └── html.xsl ├── mobi │ └── mobi.xsl └── pdf │ └── pdf.xsl ├── B-embedding-git-in-your-applications.asc ├── ch08-customizing-git.asc ├── Gemfile ├── config.rb ├── ch05-distributed-git.asc ├── script └── tag_on_master ├── .travis.yml ├── ch01-getting-started.asc ├── ch02-git-basics-chapter.asc ├── A-git-in-other-environments.asc ├── ch03-git-branching.asc ├── CONTRIBUTING.md ├── ch06-github.asc ├── progit.asc ├── ch07-git-tools.asc ├── ch09-git-and-other-systems.asc ├── ch10-git-internals.asc ├── README.asc ├── ch04-git-on-the-server.asc └── atlas.json /book/index.asc: -------------------------------------------------------------------------------- 1 | == Index 2 | -------------------------------------------------------------------------------- /book/toc.asc: -------------------------------------------------------------------------------- 1 | {{ toc }} 2 | -------------------------------------------------------------------------------- /index.asc: -------------------------------------------------------------------------------- 1 | [#index] 2 | [index] 3 | = 索引 4 | -------------------------------------------------------------------------------- /Pro.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/Pro.ico -------------------------------------------------------------------------------- /book/license.asc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == 许可证 3 | 4 | include::../LICENSE.asc[] 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Jean-Noël Avila 2 | Scott Chacon -------------------------------------------------------------------------------- /book/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/cover.png -------------------------------------------------------------------------------- /callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/1.pdf -------------------------------------------------------------------------------- /callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/1.png -------------------------------------------------------------------------------- /callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/10.pdf -------------------------------------------------------------------------------- /callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/10.png -------------------------------------------------------------------------------- /callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/2.pdf -------------------------------------------------------------------------------- /callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/2.png -------------------------------------------------------------------------------- /callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/3.pdf -------------------------------------------------------------------------------- /callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/3.png -------------------------------------------------------------------------------- /callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/4.pdf -------------------------------------------------------------------------------- /callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/4.png -------------------------------------------------------------------------------- /callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/5.pdf -------------------------------------------------------------------------------- /callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/5.png -------------------------------------------------------------------------------- /callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/6.pdf -------------------------------------------------------------------------------- /callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/6.png -------------------------------------------------------------------------------- /callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/7.pdf -------------------------------------------------------------------------------- /callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/7.png -------------------------------------------------------------------------------- /callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/8.pdf -------------------------------------------------------------------------------- /callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/8.png -------------------------------------------------------------------------------- /callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/9.pdf -------------------------------------------------------------------------------- /callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/callouts/9.png -------------------------------------------------------------------------------- /images/egit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/egit.png -------------------------------------------------------------------------------- /images/gitk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/gitk.png -------------------------------------------------------------------------------- /images/jb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/jb.png -------------------------------------------------------------------------------- /images/vs-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/vs-1.png -------------------------------------------------------------------------------- /images/vs-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/vs-2.png -------------------------------------------------------------------------------- /images/2fa-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/2fa-1.png -------------------------------------------------------------------------------- /images/areas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/areas.png -------------------------------------------------------------------------------- /images/clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/clean.png -------------------------------------------------------------------------------- /images/deltas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/deltas.png -------------------------------------------------------------------------------- /images/emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/emoji.png -------------------------------------------------------------------------------- /images/hubot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/hubot.png -------------------------------------------------------------------------------- /images/local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/local.png -------------------------------------------------------------------------------- /images/neworg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/neworg.png -------------------------------------------------------------------------------- /images/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/signup.png -------------------------------------------------------------------------------- /images/smudge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/smudge.png -------------------------------------------------------------------------------- /book/cover.html: -------------------------------------------------------------------------------- 1 |
cover
2 | -------------------------------------------------------------------------------- /images/bitnami.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/bitnami.png -------------------------------------------------------------------------------- /images/git-bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-bash.png -------------------------------------------------------------------------------- /images/git-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-gui.png -------------------------------------------------------------------------------- /images/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/lifecycle.png -------------------------------------------------------------------------------- /images/new-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/new-repo.png -------------------------------------------------------------------------------- /images/newrepo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/newrepo.png -------------------------------------------------------------------------------- /images/p4merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/p4merge.png -------------------------------------------------------------------------------- /images/posh-git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/posh-git.png -------------------------------------------------------------------------------- /images/replace1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/replace1.png -------------------------------------------------------------------------------- /images/replace2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/replace2.png -------------------------------------------------------------------------------- /images/replace3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/replace3.png -------------------------------------------------------------------------------- /images/replace4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/replace4.png -------------------------------------------------------------------------------- /images/replace5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/replace5.png -------------------------------------------------------------------------------- /images/rerere1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/rerere1.png -------------------------------------------------------------------------------- /images/rerere2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/rerere2.png -------------------------------------------------------------------------------- /images/rerere3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/rerere3.png -------------------------------------------------------------------------------- /images/reset-ex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex1.png -------------------------------------------------------------------------------- /images/reset-ex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex2.png -------------------------------------------------------------------------------- /images/reset-ex3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex3.png -------------------------------------------------------------------------------- /images/reset-ex4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex4.png -------------------------------------------------------------------------------- /images/reset-ex5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex5.png -------------------------------------------------------------------------------- /images/reset-ex6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-ex6.png -------------------------------------------------------------------------------- /images/snapshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/snapshots.png -------------------------------------------------------------------------------- /images/ssh-keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/ssh-keys.png -------------------------------------------------------------------------------- /images/zsh-oh-my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/zsh-oh-my.png -------------------------------------------------------------------------------- /images/avatar-crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/avatar-crop.png -------------------------------------------------------------------------------- /images/blink-02-pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-02-pr.png -------------------------------------------------------------------------------- /images/centralized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/centralized.png -------------------------------------------------------------------------------- /images/distributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/distributed.png -------------------------------------------------------------------------------- /images/double-dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/double-dot.png -------------------------------------------------------------------------------- /images/forkbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/forkbutton.png -------------------------------------------------------------------------------- /images/github_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/github_mac.png -------------------------------------------------------------------------------- /images/github_win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/github_win.png -------------------------------------------------------------------------------- /images/gitlab-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/gitlab-menu.png -------------------------------------------------------------------------------- /images/newrepoform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/newrepoform.png -------------------------------------------------------------------------------- /images/pr-01-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/pr-01-fail.png -------------------------------------------------------------------------------- /images/rebasing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/rebasing-1.png -------------------------------------------------------------------------------- /images/rebasing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/rebasing-2.png -------------------------------------------------------------------------------- /images/reset-hard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-hard.png -------------------------------------------------------------------------------- /images/reset-mixed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-mixed.png -------------------------------------------------------------------------------- /images/reset-path1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-path1.png -------------------------------------------------------------------------------- /images/reset-path2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-path2.png -------------------------------------------------------------------------------- /images/reset-path3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-path3.png -------------------------------------------------------------------------------- /images/reset-soft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-soft.png -------------------------------------------------------------------------------- /images/reset-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-start.png -------------------------------------------------------------------------------- /images/zsh-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/zsh-prompt.png -------------------------------------------------------------------------------- /images/advance-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/advance-master.png -------------------------------------------------------------------------------- /images/basic-rebase-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-rebase-1.png -------------------------------------------------------------------------------- /images/basic-rebase-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-rebase-2.png -------------------------------------------------------------------------------- /images/basic-rebase-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-rebase-3.png -------------------------------------------------------------------------------- /images/basic-rebase-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-rebase-4.png -------------------------------------------------------------------------------- /images/blink-01-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-01-start.png -------------------------------------------------------------------------------- /images/blink-04-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-04-email.png -------------------------------------------------------------------------------- /images/blink-06-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-06-final.png -------------------------------------------------------------------------------- /images/collaborators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/collaborators.png -------------------------------------------------------------------------------- /images/data-model-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/data-model-1.png -------------------------------------------------------------------------------- /images/data-model-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/data-model-2.png -------------------------------------------------------------------------------- /images/data-model-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/data-model-3.png -------------------------------------------------------------------------------- /images/data-model-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/data-model-4.png -------------------------------------------------------------------------------- /images/email-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/email-settings.png -------------------------------------------------------------------------------- /images/git-diff-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-diff-check.png -------------------------------------------------------------------------------- /images/git-instaweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-instaweb.png -------------------------------------------------------------------------------- /images/gitlab-groups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/gitlab-groups.png -------------------------------------------------------------------------------- /images/gitlab-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/gitlab-users.png -------------------------------------------------------------------------------- /images/head-to-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/head-to-master.png -------------------------------------------------------------------------------- /images/large-merges-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/large-merges-1.png -------------------------------------------------------------------------------- /images/large-merges-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/large-merges-2.png -------------------------------------------------------------------------------- /images/lr-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/lr-branches-1.png -------------------------------------------------------------------------------- /images/lr-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/lr-branches-2.png -------------------------------------------------------------------------------- /images/maint-01-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-01-email.png -------------------------------------------------------------------------------- /images/maint-02-merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-02-merge.png -------------------------------------------------------------------------------- /images/managed-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/managed-team-1.png -------------------------------------------------------------------------------- /images/managed-team-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/managed-team-2.png -------------------------------------------------------------------------------- /images/managed-team-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/managed-team-3.png -------------------------------------------------------------------------------- /images/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/notifications.png -------------------------------------------------------------------------------- /images/orgs-01-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/orgs-01-page.png -------------------------------------------------------------------------------- /images/orgs-02-teams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/orgs-02-teams.png -------------------------------------------------------------------------------- /images/orgs-03-audit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/orgs-03-audit.png -------------------------------------------------------------------------------- /images/public-small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/public-small-1.png -------------------------------------------------------------------------------- /images/public-small-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/public-small-2.png -------------------------------------------------------------------------------- /images/public-small-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/public-small-3.png -------------------------------------------------------------------------------- /images/reset-checkout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-checkout.png -------------------------------------------------------------------------------- /images/reset-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-workflow.png -------------------------------------------------------------------------------- /images/small-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-1.png -------------------------------------------------------------------------------- /images/small-team-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-2.png -------------------------------------------------------------------------------- /images/small-team-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-3.png -------------------------------------------------------------------------------- /images/small-team-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-4.png -------------------------------------------------------------------------------- /images/small-team-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-5.png -------------------------------------------------------------------------------- /images/small-team-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-6.png -------------------------------------------------------------------------------- /images/small-team-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-7.png -------------------------------------------------------------------------------- /images/two-branches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/two-branches.png -------------------------------------------------------------------------------- /images/your-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/your-profile.png -------------------------------------------------------------------------------- /images/account-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/account-settings.png -------------------------------------------------------------------------------- /images/advance-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/advance-testing.png -------------------------------------------------------------------------------- /images/basic-merging-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-merging-1.png -------------------------------------------------------------------------------- /images/basic-merging-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-merging-2.png -------------------------------------------------------------------------------- /images/checkout-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/checkout-master.png -------------------------------------------------------------------------------- /images/commit-and-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/commit-and-tree.png -------------------------------------------------------------------------------- /images/git-fusion-boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-fusion-boot.png -------------------------------------------------------------------------------- /images/gitlab-broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/gitlab-broadcast.png -------------------------------------------------------------------------------- /images/head-to-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/head-to-testing.png -------------------------------------------------------------------------------- /images/maint-04-target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-04-target.png -------------------------------------------------------------------------------- /images/maint-09-contrib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-09-contrib.png -------------------------------------------------------------------------------- /images/pr-02-merge-fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/pr-02-merge-fix.png -------------------------------------------------------------------------------- /images/reposettingslink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reposettingslink.png -------------------------------------------------------------------------------- /images/reset-squash-r1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-squash-r1.png -------------------------------------------------------------------------------- /images/reset-squash-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-squash-r2.png -------------------------------------------------------------------------------- /images/reset-squash-r3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/reset-squash-r3.png -------------------------------------------------------------------------------- /images/small-team-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/small-team-flow.png -------------------------------------------------------------------------------- /images/topic-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/topic-branches-1.png -------------------------------------------------------------------------------- /images/topic-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/topic-branches-2.png -------------------------------------------------------------------------------- /images/undomerge-reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/undomerge-reset.png -------------------------------------------------------------------------------- /images/undomerge-revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/undomerge-revert.png -------------------------------------------------------------------------------- /images/undomerge-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/undomerge-start.png -------------------------------------------------------------------------------- /book/06-github/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/1.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/1.png -------------------------------------------------------------------------------- /book/06-github/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/10.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/10.png -------------------------------------------------------------------------------- /book/06-github/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/2.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/2.png -------------------------------------------------------------------------------- /book/06-github/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/3.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/3.png -------------------------------------------------------------------------------- /book/06-github/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/4.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/4.png -------------------------------------------------------------------------------- /book/06-github/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/5.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/5.png -------------------------------------------------------------------------------- /book/06-github/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/6.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/6.png -------------------------------------------------------------------------------- /book/06-github/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/7.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/7.png -------------------------------------------------------------------------------- /book/06-github/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/8.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/8.png -------------------------------------------------------------------------------- /book/06-github/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/9.pdf -------------------------------------------------------------------------------- /book/06-github/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/06-github/callouts/9.png -------------------------------------------------------------------------------- /diagram-source/progit.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/diagram-source/progit.sketch -------------------------------------------------------------------------------- /images/basic-branching-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-1.png -------------------------------------------------------------------------------- /images/basic-branching-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-2.png -------------------------------------------------------------------------------- /images/basic-branching-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-3.png -------------------------------------------------------------------------------- /images/basic-branching-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-4.png -------------------------------------------------------------------------------- /images/basic-branching-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-5.png -------------------------------------------------------------------------------- /images/basic-branching-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/basic-branching-6.png -------------------------------------------------------------------------------- /images/benevolent-dictator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/benevolent-dictator.png -------------------------------------------------------------------------------- /images/blink-04-pr-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-04-pr-comment.png -------------------------------------------------------------------------------- /images/branch-and-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/branch-and-history.png -------------------------------------------------------------------------------- /images/branch_widget_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/branch_widget_mac.png -------------------------------------------------------------------------------- /images/branch_widget_win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/branch_widget_win.png -------------------------------------------------------------------------------- /images/commits-and-parents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/commits-and-parents.png -------------------------------------------------------------------------------- /images/git-osx-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-osx-installer.png -------------------------------------------------------------------------------- /images/integration-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/integration-manager.png -------------------------------------------------------------------------------- /images/maint-03-email-resp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-03-email-resp.png -------------------------------------------------------------------------------- /images/maint-05-mentions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-05-mentions.png -------------------------------------------------------------------------------- /images/maint-11-transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-11-transfer.png -------------------------------------------------------------------------------- /images/managed-team-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/managed-team-flow.png -------------------------------------------------------------------------------- /images/markdown-01-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-01-example.png -------------------------------------------------------------------------------- /images/markdown-02-tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-02-tasks.png -------------------------------------------------------------------------------- /images/markdown-05-quote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-05-quote.png -------------------------------------------------------------------------------- /images/markdown-07-emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-07-emoji.png -------------------------------------------------------------------------------- /images/mentions-01-syntax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/mentions-01-syntax.png -------------------------------------------------------------------------------- /images/mentions-02-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/mentions-02-render.png -------------------------------------------------------------------------------- /images/mentions-03-closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/mentions-03-closed.png -------------------------------------------------------------------------------- /images/merging-workflows-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-1.png -------------------------------------------------------------------------------- /images/merging-workflows-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-2.png -------------------------------------------------------------------------------- /images/merging-workflows-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-3.png -------------------------------------------------------------------------------- /images/merging-workflows-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-4.png -------------------------------------------------------------------------------- /images/merging-workflows-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-5.png -------------------------------------------------------------------------------- /images/remote-branches-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/remote-branches-1.png -------------------------------------------------------------------------------- /images/remote-branches-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/remote-branches-2.png -------------------------------------------------------------------------------- /images/remote-branches-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/remote-branches-3.png -------------------------------------------------------------------------------- /images/remote-branches-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/remote-branches-4.png -------------------------------------------------------------------------------- /images/remote-branches-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/remote-branches-5.png -------------------------------------------------------------------------------- /images/scripting-07-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-07-status.png -------------------------------------------------------------------------------- /images/undomerge-revert2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/undomerge-revert2.png -------------------------------------------------------------------------------- /images/undomerge-revert3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/undomerge-revert3.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/1.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/1.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/2.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/2.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/3.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/3.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/4.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/4.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/5.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/5.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/6.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/6.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/7.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/7.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/8.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/8.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/9.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/9.png -------------------------------------------------------------------------------- /images/centralized_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/centralized_workflow.png -------------------------------------------------------------------------------- /images/interesting-rebase-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/interesting-rebase-1.png -------------------------------------------------------------------------------- /images/interesting-rebase-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/interesting-rebase-2.png -------------------------------------------------------------------------------- /images/interesting-rebase-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/interesting-rebase-3.png -------------------------------------------------------------------------------- /images/interesting-rebase-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/interesting-rebase-4.png -------------------------------------------------------------------------------- /images/interesting-rebase-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/interesting-rebase-5.png -------------------------------------------------------------------------------- /images/maint-06-unsubscribe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-06-unsubscribe.png -------------------------------------------------------------------------------- /images/markdown-08-drag-drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-08-drag-drop.png -------------------------------------------------------------------------------- /images/merging-workflows-4 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/merging-workflows-4 2.png -------------------------------------------------------------------------------- /images/perils-of-rebasing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/perils-of-rebasing-1.png -------------------------------------------------------------------------------- /images/perils-of-rebasing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/perils-of-rebasing-2.png -------------------------------------------------------------------------------- /images/perils-of-rebasing-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/perils-of-rebasing-3.png -------------------------------------------------------------------------------- /images/perils-of-rebasing-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/perils-of-rebasing-4.png -------------------------------------------------------------------------------- /images/perils-of-rebasing-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/perils-of-rebasing-5.png -------------------------------------------------------------------------------- /images/scripting-01-services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-01-services.png -------------------------------------------------------------------------------- /images/scripting-03-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-03-webhook.png -------------------------------------------------------------------------------- /images/scripting-06-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-06-comment.png -------------------------------------------------------------------------------- /book/07-git-tools/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/10.pdf -------------------------------------------------------------------------------- /book/07-git-tools/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/07-git-tools/callouts/10.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/1.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/1.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/2.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/2.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/3.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/3.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/4.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/4.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/5.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/5.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/6.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/6.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/7.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/7.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/8.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/8.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/9.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/9.png -------------------------------------------------------------------------------- /images/blink-05-general-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-05-general-comment.png -------------------------------------------------------------------------------- /images/blink-pull-request-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-pull-request-open.png -------------------------------------------------------------------------------- /images/maint-07-notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-07-notifications.png -------------------------------------------------------------------------------- /images/maint-10-default-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-10-default-branch.png -------------------------------------------------------------------------------- /images/markdown-03-task-summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-03-task-summary.png -------------------------------------------------------------------------------- /images/markdown-04-fenced-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-04-fenced-code.png -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/10.pdf -------------------------------------------------------------------------------- /book/B-embedding-git/callouts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/book/B-embedding-git/callouts/10.png -------------------------------------------------------------------------------- /images/blink-03-pull-request-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-03-pull-request-open.png -------------------------------------------------------------------------------- /images/git-fusion-perforce-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/git-fusion-perforce-graph.png -------------------------------------------------------------------------------- /images/markdown-06-emoji-complete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/markdown-06-emoji-complete.png -------------------------------------------------------------------------------- /images/scripting-02-email-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-02-email-service.png -------------------------------------------------------------------------------- /images/scripting-04-webhook-debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-04-webhook-debug.png -------------------------------------------------------------------------------- /images/scripting-05-access-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/scripting-05-access-token.png -------------------------------------------------------------------------------- /images/blink-pull-request-open copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/blink-pull-request-open copy.png -------------------------------------------------------------------------------- /images/maint-08-notifications-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progit/progit2-zh/HEAD/images/maint-08-notifications-page.png -------------------------------------------------------------------------------- /book/dedication.asc: -------------------------------------------------------------------------------- 1 | [dedication] 2 | == 献辞 3 | 4 | _致我的妻子,Becky,没有她的话这段冒险不会开始。—— Ben_ 5 | 6 | _谨以此书献给我的家人。 7 | 给这些年一直支持着我的妻子 Jessica 和女儿 Josephine, 8 | 还有那些在我风烛残年之时还能支持我的人。—— Scott_ 9 | -------------------------------------------------------------------------------- /LICENSE.asc: -------------------------------------------------------------------------------- 1 | 本作品在“创作共用 署名-非商业性使用-相同方式共享 3.0 未本地化版本 (CC BY-NC-SA 3.0)”许可协议下授权。 2 | 要阅览该许可的副本,请访问 https://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh 3 | 或者写信向 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA 获取。 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | output 2 | .DS_Store 3 | 4 | # build artifacts 5 | Gemfile.lock 6 | progit.html 7 | progit.pdf 8 | progit.pdfmarks 9 | progit.epub 10 | progit.fb2.zip 11 | progit-kf8.epub 12 | progit.mobi 13 | contributors.txt 14 | progit.mobi8 15 | -------------------------------------------------------------------------------- /.tgitconfig: -------------------------------------------------------------------------------- 1 | [bugtraq] 2 | url = https://github.com/progit/progit2/issues/%BUGID% 3 | logregex = "(?:[Cc]lose[sd]?|[Ff]ix(?:e[sd])?|[Rr]esolve[sd]?):?\\s+(?:[Ii]ssues?\\s+#?|#)\\d+(?:(?:,|\\s+and)\\s+(?:[Ii]ssues?\\s+#?|#)\\d+)*\n(\\d+)" 4 | 5 | [tgit] 6 | icon = Pro.ico 7 | -------------------------------------------------------------------------------- /book/preface_ben.asc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == Ben Straub 序 3 | 4 | 本书的第一版就是将我与 Git 结下不解之缘的原因。书中采用的是我引进的做软件的风格,这种风格比我之前看到的任何事情都要自然。那时我已经做了好几年开发者了,但是这本书将我指引到一条更加精彩的道路上。 5 | 6 | 几年之后的现在,我是 Git 的一个主要实现的贡献者,我在最大的 Git 托管公司工作,我已经环游世界教人们使用 Git。当 Scott 问我是否有兴趣在第二版上工作时,我甚至连想都没想就答应了。 7 | 8 | 能在这本书上工作是一份巨大的快乐与荣耀。我希望它能像帮助我一样帮助你。 9 | -------------------------------------------------------------------------------- /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | # Update your Gemfile (& lockfiles) as soon as 4 | # new versions are published to the RubyGems registry 5 | - package_manager: "ruby:bundler" 6 | directory: "/" 7 | update_schedule: "live" 8 | 9 | # Apply default reviewer and label to created 10 | # pull requests 11 | default_reviewers: 12 | - "ben" 13 | default_labels: 14 | - "dependabot" 15 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/visualstudio.asc: -------------------------------------------------------------------------------- 1 | === Visual Studio 中的 Git 2 | 3 | (((Visual Studio))) 4 | 从 Visual Studio 2019 16.8 版本开始,Visual Studio 将 Git 工具直接内置到 IDE 中。 5 | 6 | 工具支持以下 Git 功能: 7 | 8 | * 创建与克隆仓库。 9 | * 打开与浏览仓库的历史。 10 | * 创建与检出分支与标签。 11 | * 储藏、暂存与提交改动。 12 | * 抓取、拉取、推送或同步提交。 13 | * 合并与变基分支。 14 | * 解决合并冲突。 15 | * 查看差异。 16 | * ... 等等。 17 | 18 | 阅读 https://docs.microsoft.com/visualstudio/version-control[official documentation^] 以了解更多内容。 19 | -------------------------------------------------------------------------------- /book/04-git-server/sections/hosted.asc: -------------------------------------------------------------------------------- 1 | === 第三方托管的选择 2 | 3 | 如果不想设立自己的 Git 服务器,你可以选择将你的 Git 项目托管到一个外部专业的托管网站。 4 | 这带来了一些好处:一个托管网站可以用来快速建立并开始项目,且无需进行服务器维护和监控工作。 5 | 即使你在内部设立并且运行了自己的服务器,你仍然可以把你的开源代码托管在公共托管网站——这通常更有助于开源社区来发现和帮助你。 6 | 7 | 现在,有非常多的托管供你选择,每个选择都有不同的优缺点。 8 | 欲查看最新列表,请浏览 Git 维基的 GitHosting 页面 https://git.wiki.kernel.org/index.php/GitHosting[] 9 | 10 | 我们会在 <> 详细讲解 GitHub,作为目前最大的 Git 托管平台, 11 | 你很可能需要与托管在 GitHub 上的项目进行交互,而且你也很可能并不想去设立你自己的 Git 服务器。 12 | -------------------------------------------------------------------------------- /book/01-introduction/sections/command-line.asc: -------------------------------------------------------------------------------- 1 | === 命令行 2 | 3 | Git 有多种使用方式。 4 | 你可以使用原生的命令行模式,也可以使用 GUI 模式,这些 GUI 软件也能提供多种功能。 5 | 在本书中,我们将使用命令行模式。 6 | 这是因为首先,只有在命令行模式下你才能执行 Git 的 *所有* 命令,而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度。 7 | 如果你学会了在命令行下如何操作,那么你在操作 GUI 软件时应该也不会遇到什么困难,但是,反之则不成立。 8 | 此外,由于每个人的想法与侧重点不同,不同的人常常会安装不同的 GUI 软件,但 _所有_ 人一定会有命令行工具。 9 | 10 | 假如你是 macOS 用户,我们希望你懂得如何使用终端(Terminal);假如你是 Windows 用户,我们希望你懂得如何使用命令窗口(Command Prompt)或 PowerShell。 11 | 如果你尚未掌握以上技能,我们建议你先停下来快速学习一下,本书中的讲述和举例将用到这些技能。 12 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/jetbrainsides.asc: -------------------------------------------------------------------------------- 1 | === IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git 2 | 3 | (((JetBrains))) 4 | JetBrains IDEs(比如 IntelliJ IDEA,PyCharm,WebStorm,PhpStorm,RubyMine,以及其他)自带 Git 集成插件。 5 | 在 IDE 中提供了一个专门的页面,可以使用 Git 和 GitHub 的 Pull Request。 6 | 7 | .JetBrains IDEs 中的版本控制工具窗口。 8 | image::images/jb.png[JetBrains IDEs 中的版本控制工具窗口。] 9 | 10 | 该集成插件依赖于 Git 的命令行客户端,所以需要先安装一个 Git 客户端。 11 | 官方文档请访问 https://www.jetbrains.com/help/idea/using-git-integration.html。 12 | -------------------------------------------------------------------------------- /.github/workflows/pr-build.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Build 2 | 3 | on: 4 | pull_request: 5 | branches: [ main, master ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | 13 | - name: Set up Ruby 14 | uses: ruby/setup-ruby@v1 15 | with: 16 | ruby-version: 2.7 17 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 18 | 19 | - name: Build book 20 | run: bundle exec rake book:build 21 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/sublimetext.asc: -------------------------------------------------------------------------------- 1 | === Sublime Text 中的 Git 2 | 3 | (((Sublime Text))) 4 | 从 3.2 版本开始,Sublime Text 在编辑器内集成了 Git。 5 | 6 | 功能如下: 7 | 8 | * 侧边栏将会使用图标来指明文件及文件夹的 Git 状态。 9 | * 被你的 .gitignore 文件所指定忽略的文件以及文件夹会在侧边栏褪色显示。 10 | * 在状态栏,你能够查看当前所在分支以及你做了多少修改。 11 | * 对一个文件的所有改动都会通过行号槽上的记号显示出来。 12 | * 你能够在 Sublime Text 内使用 Sublime Merge 这个 Git 客户端的部分功能。 13 | 要求安装 Sublime Merge: 14 | https://www.sublimemerge.com/。 15 | 16 | Sublime Text 的官方文档请访问:https://www.sublimetext.com/docs/3/git_integration.html。 17 | -------------------------------------------------------------------------------- /book/B-embedding-git/sections/command-line.asc: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /theme/epub/layout.html: -------------------------------------------------------------------------------- 1 | {{ doctype }} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ title }} 10 | 11 | 12 | {{ content }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /B-embedding-git-in-your-applications.asc: -------------------------------------------------------------------------------- 1 | [[B-embedding-git-in-your-applications]] 2 | [appendix] 3 | == 在你的应用中嵌入 Git 4 | 5 | 如果你的应用程序的目标用户是开发者,那么在其中集成源码控制功能会让他们从中受益。 6 | 甚至对于文档编辑器等并非面向程序员的应用,也可以从版本控制系统中受益,Git 的工作模式在多种场景下表现得都非常出色。 7 | 8 | 如果你想将 Git 整合进你的应用程序,那么通常有两种可行的选择:启动 shell 来调用 Git 的命令行程序,或者将 Git 库嵌入到你的应用中。 9 | 10 | include::book/B-embedding-git/sections/command-line.asc[] 11 | 12 | include::book/B-embedding-git/sections/libgit2.asc[] 13 | 14 | include::book/B-embedding-git/sections/jgit.asc[] 15 | 16 | include::book/B-embedding-git/sections/go-git.asc[] 17 | 18 | include::book/B-embedding-git/sections/dulwich.asc[] 19 | 20 | -------------------------------------------------------------------------------- /ch08-customizing-git.asc: -------------------------------------------------------------------------------- 1 | [[ch08-customizing-git]] 2 | == 自定义 Git 3 | 4 | 到目前为止,我们已经阐述了 Git 基本的运作机制和使用方式,介绍了许多 Git 提供的工具来帮助你简单且有效地使用它。 5 | 在本章,我们将演示如何借助 Git 的一些重要的配置方法和钩子机制,来满足自定义的需求。 6 | 通过这些工具,它会和你、你的公司或你的团队配合得天衣无缝。 7 | 8 | include::book/08-customizing-git/sections/config.asc[] 9 | 10 | include::book/08-customizing-git/sections/attributes.asc[] 11 | 12 | include::book/08-customizing-git/sections/hooks.asc[] 13 | 14 | include::book/08-customizing-git/sections/policy.asc[] 15 | 16 | === 总结 17 | 18 | 我们已经阐述了大部分通过自定义 Git 客户端和服务端来适应自己工作流程和项目内容的方式。 19 | 你已经学到各种各样的设置项、基于文件的选项和事件钩子,还建立了一个示例用的强制策略服务器。 20 | 无论创造出了什么样的工作流程,你都能使 Git 与它珠联璧合。 21 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/visualstudiocode.asc: -------------------------------------------------------------------------------- 1 | === Visual Studio Code 中的 Git 2 | 3 | (((Visual Studio Code))) 4 | Visual Studio Code 自带对 Git 的支持。 5 | 你需要安装 2.0.0(及以上)版本的 Git。 6 | 7 | 主要功能如下: 8 | 9 | * 在行号槽显示你正在编辑的文件的改动情况。 10 | * Git 状态栏(位于左下角)会显示当前所在分支,编辑指示符以及未提交或者未拉取的提交的数量。 11 | * 你能够在编辑器内完成常用的 Git 操作: 12 | ** 初始化一个仓库。 13 | ** 克隆一个仓库。 14 | ** 新建分支和标签。 15 | ** 暂存和提交修改。 16 | ** 对一个远程分支进行推送/拉取/同步。 17 | ** 解决合并冲突。 18 | ** 查看比较。 19 | * 配合一个扩展,你也能够处理 GitHub 的拉取请求: 20 | https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github。 21 | 22 | 官方文档请访问: https://code.visualstudio.com/Docs/editor/versioncontrol。 23 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'ffi', '1.16.3' 4 | gem 'rake' 5 | gem 'asciidoctor', '2.0.12' 6 | 7 | gem 'json' 8 | gem 'awesome_print' 9 | 10 | gem 'ttfunk', '1.5.1' 11 | gem 'asciidoctor-fb2' 12 | gem 'asciidoctor-epub3', '1.5.0.alpha.11' 13 | gem 'asciidoctor-pdf', '1.5.0.alpha.16' 14 | gem 'asciidoctor-pdf-cjk', '~> 0.1.3' 15 | gem 'asciidoctor-pdf-cjk-kai_gen_gothic', github: 'Sherry520/asciidoctor-pdf-cjk-kai_gen_gothic' 16 | 17 | gem 'coderay' 18 | gem 'pygments.rb' 19 | gem 'thread_safe' 20 | gem 'epubcheck-ruby' 21 | gem 'html-proofer' 22 | 23 | gem 'kindlegen', '3.1.1' 24 | gem 'nokogiri', '~> 1.13', '>= 1.13.10' 25 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | Bundler.require(:default) 2 | 3 | class TrailingTreeprocessor < Asciidoctor::Extensions::Treeprocessor 4 | def process document 5 | return unless document.blocks? 6 | process_blocks document 7 | nil 8 | end 9 | 10 | def process_blocks node 11 | node.blocks.each_with_index do |block, index| 12 | if block.context == :paragraph 13 | node.blocks[index] = create_paragraph block.document, block.content.gsub("\n", ''), block.attributes 14 | else 15 | process_blocks block 16 | end 17 | end 18 | end 19 | end 20 | 21 | Asciidoctor::Extensions.register do 22 | treeprocessor TrailingTreeprocessor 23 | end 24 | -------------------------------------------------------------------------------- /ch05-distributed-git.asc: -------------------------------------------------------------------------------- 1 | [[ch05-distributed-git]] 2 | == 分布式 Git 3 | 4 | (((distributed git))) 5 | 你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令。你现在可以学习如何利用 Git 提供的一些分布式工作流程了。 6 | 7 | 这一章中,你将会学习如何作为贡献者或整合者,在一个分布式协作的环境中使用 Git。 8 | 你会学习为一个项目成功地贡献代码,并接触一些最佳实践方式,让你和项目的维护者能轻松地完成这个过程。另外,你也会学到如何管理有很多开发者提交贡献的项目。 9 | 10 | include::book/05-distributed-git/sections/distributed-workflows.asc[] 11 | 12 | include::book/05-distributed-git/sections/contributing.asc[] 13 | 14 | include::book/05-distributed-git/sections/maintaining.asc[] 15 | 16 | === 总结 17 | 18 | 你现在能自如地使用 Git 为项目做出贡献、维护自己的项目或采纳其他用户的贡献了。 19 | 恭喜你成为了一个高效的 Git 开发者! 20 | 下一章中,你将会学到如何使用规模最大最流行的 Git 托管服务,GitHub。 21 | -------------------------------------------------------------------------------- /script/tag_on_master: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This is for running on Travis. It automatically tags any merge to Master as a release in the 2.1.x series. 4 | if [[ $TRAVIS_PULL_REQUEST != 'false' || "$TRAVIS_BRANCH" != 'master' ]]; then 5 | # Don't run on pull requests 6 | echo 'This only runs on a merge to master.' 7 | exit 0 8 | fi 9 | 10 | # Compute the next tag number 11 | LASTPATCH=$(git describe --tags | cut -d- -f1 | cut -d. -f3) 12 | PATCH=$(($LASTPATCH+1)) 13 | echo $PATCH 14 | 15 | # Create a tag 16 | curl -H "Authorization: token $GITHUB_KEY" \ 17 | -X POST \ 18 | -d "{\"ref\":\"refs/tags/2.1.$PATCH\", \"sha\":\"$TRAVIS_COMMIT\"}" \ 19 | https://api.github.com/repos/progit/progit2/git/refs 20 | -------------------------------------------------------------------------------- /book/01-introduction/sections/history.asc: -------------------------------------------------------------------------------- 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 | 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统(参见 <>)。 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | sudo: false 3 | git: 4 | depth: false 5 | cache: bundler 6 | before_install: 7 | - wget https://raw.githubusercontent.com/progit/progit2-pub/master/bootstrap.sh 8 | - sh bootstrap.sh 9 | script: bundle exec rake book:build 10 | after_success: bundle exec rake book:tag 11 | deploy: 12 | provider: releases 13 | file_glob: true 14 | file: 15 | - progit*.epub 16 | - progit*.mobi 17 | - progit*.pdf 18 | skip_cleanup: true 19 | on: 20 | tags: true 21 | api-key: $GITHUB_API_TOKEN 22 | branches: 23 | only: 24 | - master 25 | - /^2\.1(\.\d+)+$/ 26 | 27 | addons: 28 | apt: 29 | packages: 30 | - epubcheck 31 | notifications: 32 | email: 33 | on_success: never 34 | on_failure: always 35 | -------------------------------------------------------------------------------- /ch01-getting-started.asc: -------------------------------------------------------------------------------- 1 | [[ch01-getting-started]] 2 | == 起步 3 | 4 | 本章为 Git 入门。 5 | 我们从介绍版本控制工具的背景知识开始,然后讲解如何在你的系统上运行 Git,最后是关于如何设置 Git 以便开始工作。 6 | 通过本章的学习,你应该能了解为什么 Git 这么流行,为什么你应该使用 Git 以及你应该如何设置以便使用 Git。 7 | 8 | include::book/01-introduction/sections/about-version-control.asc[] 9 | 10 | include::book/01-introduction/sections/history.asc[] 11 | 12 | include::book/01-introduction/sections/what-is-git.asc[] 13 | 14 | include::book/01-introduction/sections/command-line.asc[] 15 | 16 | include::book/01-introduction/sections/installing.asc[] 17 | 18 | include::book/01-introduction/sections/first-time-setup.asc[] 19 | 20 | include::book/01-introduction/sections/help.asc[] 21 | 22 | === 总结 23 | 24 | 你应该已经对 Git 是什么、Git 与你可能正在使用的集中式版本控制系统有何区别等问题有了基本的了解。 25 | 现在,在你的系统中应该也有了一份能够工作的 Git 版本。 26 | 是时候开始学习有关 Git 的基础知识了。 27 | -------------------------------------------------------------------------------- /ch02-git-basics-chapter.asc: -------------------------------------------------------------------------------- 1 | [[ch02-git-basics-chapter]] 2 | == Git 基础 3 | 4 | 如果你只想通过阅读一章来学习 Git,那么本章将是你的不二选择。 5 | 本章涵盖了你在使用 Git 完成各种工作时将会用到的各种基本命令。 6 | 在学习完本章之后,你应该能够配置并初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交(commit)更改。 7 | 本章也将向你演示了如何配置 Git 来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操作、如何浏览你的项目的历史版本以及不同提交(commits)之间的差异、如何向你的远程仓库推送(push)以及如何从你的远程仓库拉取(pull)文件。 8 | 9 | include::book/02-git-basics/sections/getting-a-repository.asc[] 10 | 11 | include::book/02-git-basics/sections/recording-changes.asc[] 12 | 13 | include::book/02-git-basics/sections/viewing-history.asc[] 14 | 15 | include::book/02-git-basics/sections/undoing.asc[] 16 | 17 | include::book/02-git-basics/sections/remotes.asc[] 18 | 19 | include::book/02-git-basics/sections/tagging.asc[] 20 | 21 | include::book/02-git-basics/sections/aliases.asc[] 22 | 23 | === 总结 24 | 25 | 现在,你应该能完成所有 Git 基本的本地操作了-创建或克隆一个仓库、进行更改、暂存并提交这些更改、浏览仓库从创建到现在的所有更改历史。 26 | 接下来,本书将介绍 Git 的杀手级特性:分支模型。 27 | -------------------------------------------------------------------------------- /A-git-in-other-environments.asc: -------------------------------------------------------------------------------- 1 | [[A-git-in-other-environments]] 2 | [appendix] 3 | == 在其它环境中使用 Git 4 | 5 | 如果你读完了本书,那就已经掌握了很多在命令行中使用 Git 的知识了。 6 | 你可以用它来处理本地文件,通过网络连接到他人的仓库,以及高效地与他人协同工作。 7 | 不过故事到这儿还没结束。Git 通常还会作为一个组件在更大的生态系统中使用, 8 | 而终端并不总是最佳的使用方式。现在我们来看看 Git 在其它环境中的使用, 9 | 以及其它应用(包括你的应用)是如何与 Git 协同使用的。 10 | 11 | include::book/A-git-in-other-environments/sections/guis.asc[] 12 | 13 | include::book/A-git-in-other-environments/sections/visualstudio.asc[] 14 | 15 | include::book/A-git-in-other-environments/sections/visualstudiocode.asc[] 16 | 17 | include::book/A-git-in-other-environments/sections/jetbrainsides.asc[] 18 | 19 | include::book/A-git-in-other-environments/sections/sublimetext.asc[] 20 | 21 | include::book/A-git-in-other-environments/sections/bash.asc[] 22 | 23 | include::book/A-git-in-other-environments/sections/zsh.asc[] 24 | 25 | include::book/A-git-in-other-environments/sections/powershell.asc[] 26 | 27 | === 总结 28 | 29 | 现在你已经学会如何在日常使用的工具中驾驭强大的 Git,以及如何在自己的程序中访问 Git 仓库了。 30 | -------------------------------------------------------------------------------- /book/B-embedding-git/sections/dulwich.asc: -------------------------------------------------------------------------------- 1 | === Dulwich 2 | 3 | (((Dulwich)))(((Python))) 4 | 这还有一个纯-Python 的 Git 实现——Dulwich。 5 | 该项目托管在 https://www.dulwich.io/[]。 6 | 它旨在在提供一个与 Git 存储库(本地和远程)的接口,该接口不直接调用 git,而是使用纯 Python。 7 | 它有一个可选的 C 扩展,可以显著提高性能。 8 | 9 | Dulwich 遵循 git 设计,将 API 分为两个基本级别:底层命令和上层命令。 10 | 11 | 下面是一个使用低级 API 获取上次提交的提交消息的例子: 12 | 13 | [source, python] 14 | ---- 15 | from dulwich.repo import Repo 16 | r = Repo('.') 17 | r.head() 18 | # '57fbe010446356833a6ad1600059d80b1e731e15' 19 | 20 | c = r[r.head()] 21 | c 22 | # 23 | 24 | c.message 25 | # 'Add note about encoding.\n' 26 | ---- 27 | 28 | 要使用高级上层命令 API 打印提交日志,可以使用: 29 | 30 | [source, python] 31 | ---- 32 | from dulwich import porcelain 33 | porcelain.log('.', max_entries=1) 34 | 35 | #commit: 57fbe010446356833a6ad1600059d80b1e731e15 36 | #Author: Jelmer Vernooij 37 | #Date: Sat Apr 29 2017 23:57:34 +0000 38 | ---- 39 | 40 | 41 | ==== 拓展阅读 42 | 43 | 在官方网站 https://www.dulwich.io[] 上可以找到 API 文档、教程和许多关于如何使用 Dulwich 完成特定任务的示例。 44 | -------------------------------------------------------------------------------- /book/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.exist? 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'] and user == known['username'] 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 | -------------------------------------------------------------------------------- /ch03-git-branching.asc: -------------------------------------------------------------------------------- 1 | [[ch03-git-branching]] 2 | == Git 分支 3 | 4 | (((branches))) 5 | 几乎所有的版本控制系统都以某种形式支持分支。 6 | 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。 7 | 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费很多时间。 8 | 9 | 有人把 Git 的分支模型称为它的“必杀技特性”,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 10 | 为何 Git 的分支模型如此出众呢? 11 | Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 12 | 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 13 | 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。 14 | 15 | include::book/03-git-branching/sections/nutshell.asc[] 16 | 17 | include::book/03-git-branching/sections/basic-branching-and-merging.asc[] 18 | 19 | include::book/03-git-branching/sections/branch-management.asc[] 20 | 21 | include::book/03-git-branching/sections/workflows.asc[] 22 | 23 | include::book/03-git-branching/sections/remote-branches.asc[] 24 | 25 | include::book/03-git-branching/sections/rebasing.asc[] 26 | 27 | === 总结 28 | 29 | 我们已经讲完了 Git 分支与合并的基础知识。 30 | 你现在应该能自如地创建并切换至新分支、在不同分支之间切换以及合并本地分支。 31 | 你现在应该也能通过推送你的分支至共享服务以分享它们、使用共享分支与他人协作以及在共享之前使用变基操作合并你的分支。 32 | 下一章,我们将要讲到,如果你想要运行自己的 Git 仓库托管服务器,你需要知道些什么。 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 向 Pro Git(第二版 简体中文)贡献 2 | 3 | ## 授权许可 4 | 5 | 向本仓库发起一个拉取请求,意味着你同意在 [项目授权许可](LICENSE.asc) 下提供你的工作。 6 | 同样,因为未来打印版本的需要,你同意以这种许可授权你的工作给 @ben 与 @schacon。 7 | 你的修改可能会出现在一个印刷版本中,你将被包括在 [贡献者列表](book/contributors.asc)中 。 8 | 9 | ## 发起一个 Issue 10 | 11 | 在发起一个 Issue 前,请在 bug 跟踪系统中搜索是否已有类似的问题。 12 | 13 | 此外,如果该问题是在 git-scm.com 网站上发现的,请再次确认 pdf 版本中是否仍有此问题。 14 | 该问题可能已被修复,但修改内容尚未部署。 15 | 16 | ## 小的修正 17 | 18 | 如果我们认同你的勘误和基本说明能够提升内容质量,那么它们将会被接受。 19 | 你也可以发起一个 Issue,这样我们可以确定该问题是否需要解决,以及如何解决。 20 | 21 | 如果你之前从未发起过 Issue,可参考 [流程向导](https://guides.github.com/introduction/flow/)。 22 | 23 | ## 大范围重写 24 | 25 | 在开始重写前,请先发起一个 Issue 讨论一下。这些改动往往非常主观,经常只为少数人澄清事实,很少值得花时间来接受它们。专业的编辑已经多次审核过这些内容,尽管你的文字品味和语法可能比我们更好一些,但你所写的内容不太可能 *如此* 地优秀以至于值得修改一大片文字。 26 | 27 | ## 图表 28 | 29 | 本书中使用的图片是使用 [Sketch 3](http://bohemiancoding.com/sketch/) 和 [包含的 sketchbook 文件](diagram-source/progit.sketch) 生成的。 30 | 31 | 要添加一个图表: 32 | 33 | 1. 向 sketchbook 添加一页。尽可能尝试使用内置符号。 34 | 2. 向你的页中添加一个 "slice"。并给它一个相对于源代码根目录的与目标PNG文件名一致的名字。 35 | 3. 确保你的 slice 设置导出为 "800w"。 36 | 37 | ## 翻译 38 | 39 | 如果你想将 Pro Git 翻译到你的语言,请参考 [TRANSLATING.md](TRANSLATING.md) 文件。 40 | -------------------------------------------------------------------------------- /ch06-github.asc: -------------------------------------------------------------------------------- 1 | [[ch06-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 上面的项目进行合作没有兴趣,可以直接跳到 <> 这一章。 13 | 14 | [WARNING] 15 | .接口的改变 16 | ==== 17 | 需要注意一点,同很多活跃的网站一样,书中截取的界面会随时间而改变。 18 | 希望我们试图表达的核心思想一直是不变的,但是,如果你想要这些截图的更新版本,本书的在线版本或许有更新的截图。 19 | ==== 20 | 21 | include::book/06-github/sections/1-setting-up-account.asc[] 22 | 23 | include::book/06-github/sections/2-contributing.asc[] 24 | 25 | include::book/06-github/sections/3-maintaining.asc[] 26 | 27 | include::book/06-github/sections/4-managing-organization.asc[] 28 | 29 | include::book/06-github/sections/5-scripting.asc[] 30 | 31 | === 总结 32 | 33 | 现在你已经是一名 GitHub 用户了。 34 | 你知道了如何创建账户、管理组织、创建和推送版本库、向别人的项目提供贡献以及接受别人的贡献。 35 | 在下一章中,你将学习更多强有力的工具,以及处理复杂情况的知识,这些将使你成为真正的 Git 大师。 36 | -------------------------------------------------------------------------------- /progit.asc: -------------------------------------------------------------------------------- 1 | = Pro Git 2 | Scott Chacon; Ben Straub 3 | :doctype: book 4 | :docinfo: 5 | :toc: 6 | :toclevels: 2 7 | :pagenums: 8 | :front-cover-image: image:book/cover.png[width=1050,height=1600] 9 | :icons: font 10 | :toc-title: 目录 11 | :appendix-caption: 附录 12 | 13 | 14 | ifdef::ebook-format[:leveloffset: -1] 15 | 16 | include::book/license.asc[] 17 | 18 | include::book/preface_schacon.asc[] 19 | 20 | include::book/preface_ben.asc[] 21 | 22 | include::book/dedication.asc[] 23 | 24 | include::book/contributors.asc[] 25 | 26 | include::book/introduction.asc[] 27 | 28 | include::ch01-getting-started.asc[] 29 | 30 | include::ch02-git-basics-chapter.asc[] 31 | 32 | include::ch03-git-branching.asc[] 33 | 34 | include::ch04-git-on-the-server.asc[] 35 | 36 | include::ch05-distributed-git.asc[] 37 | 38 | include::ch06-github.asc[] 39 | 40 | include::ch07-git-tools.asc[] 41 | 42 | include::ch08-customizing-git.asc[] 43 | 44 | include::ch09-git-and-other-systems.asc[] 45 | 46 | include::ch10-git-internals.asc[] 47 | 48 | include::A-git-in-other-environments.asc[] 49 | 50 | include::B-embedding-git-in-your-applications.asc[] 51 | 52 | include::C-git-commands.asc[] 53 | 54 | ifndef::ebook-format[include::index.asc[]] 55 | -------------------------------------------------------------------------------- /ch07-git-tools.asc: -------------------------------------------------------------------------------- 1 | [[ch07-git-tools]] 2 | == Git 工具 3 | 4 | 现在,你已经学习了管理或者维护 Git 仓库、实现代码控制所需的大多数日常命令和工作流程。 5 | 你已经尝试了跟踪和提交文件的基本操作,并且掌握了暂存区和轻量级地分支及合并的威力。 6 | 7 | 接下来你将学习一些 Git 的强大功能,这些功能你可能并不会在日常操作中使用,但在某些时候你可能会需要。 8 | 9 | include::book/07-git-tools/sections/revision-selection.asc[] 10 | 11 | include::book/07-git-tools/sections/interactive-staging.asc[] 12 | 13 | include::book/07-git-tools/sections/stashing-cleaning.asc[] 14 | 15 | include::book/07-git-tools/sections/signing.asc[] 16 | 17 | include::book/07-git-tools/sections/searching.asc[] 18 | 19 | include::book/07-git-tools/sections/rewriting-history.asc[] 20 | 21 | include::book/07-git-tools/sections/reset.asc[] 22 | 23 | include::book/07-git-tools/sections/advanced-merging.asc[] 24 | 25 | include::book/07-git-tools/sections/rerere.asc[] 26 | 27 | include::book/07-git-tools/sections/debugging.asc[] 28 | 29 | include::book/07-git-tools/sections/submodules.asc[] 30 | 31 | include::book/07-git-tools/sections/bundling.asc[] 32 | 33 | include::book/07-git-tools/sections/replace.asc[] 34 | 35 | include::book/07-git-tools/sections/credentials.asc[] 36 | 37 | === 总结 38 | 39 | 你已经接触了很多能够精确地操控提交和暂存区的高级工具。 40 | 当你碰到问题时,你应该可以很容易找出是哪个分支在什么时候由谁引入了它们。 41 | 如果你想在项目中使用子项目,你也已经知道如何来满足这些需求。 42 | 到此,你应该能毫无压力地在命令行中使用 Git 来完成日常中的大部分事情。 43 | -------------------------------------------------------------------------------- /.github/workflows/release-on-merge.yml: -------------------------------------------------------------------------------- 1 | name: Release on push to main 2 | 3 | on: 4 | push: 5 | branches: [ main, master ] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 14 | - name: Compute tag name 15 | id: compute-tag 16 | run: | 17 | echo Computing next tag number 18 | LASTPATCH=$(git describe --tags | cut -d- -f1 | cut -d. -f3) 19 | PATCH=$(($LASTPATCH+1)) 20 | echo "tagname=2.1.${PATCH}" >> $GITHUB_OUTPUT 21 | echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT 22 | 23 | - name: Set up Ruby 24 | uses: ruby/setup-ruby@v1 25 | with: 26 | ruby-version: 2.7 27 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 28 | 29 | - name: Build release assets 30 | run: bundle exec rake book:build 31 | 32 | - name: Create release 33 | uses: ncipollo/release-action@v1 34 | with: 35 | token: ${{ secrets.GITHUB_TOKEN }} 36 | tag: ${{ steps.compute-tag.outputs.tagname }} 37 | commit: ${{ steps.compute-tag.outputs.branch }} 38 | artifacts: './progit.epub,./progit.fb2.zip,./progit.mobi,./progit.pdf,./progit.html' 39 | -------------------------------------------------------------------------------- /book/preface_schacon.asc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == Scott Chacon 序 3 | 4 | 欢迎来到 Pro Git 第二版。 5 | 第一版出版到现在已经过去了四年。 6 | 到今天,Git 虽然出现了许多改变,但是还有很多重要的事情一如昨日。 7 | 因为 Git 核心团队对保持向后兼容性异常固执,所以直到今天大多数核心命令与概念依然有效,但是围绕 Git 的社区还是有一些重大的增加与改变。 8 | 本书的第二版就是为了更新书籍并讲解那些改动以使其对新用户更有帮助。 9 | 10 | 当我写第一版时,Git 对于超级黑客来说还是一个相对难用,只能勉强接受的工具。 11 | 它开始在特定的社区中快速发展,但是还没有达到像今天一样无处不在的地步。 12 | 自那时起,几乎每一个开源社区都采用了它。 13 | Git 在 Windows 上取得了难以置信的进步,包括所有平台的图形用户界面对它的支持、IDE 的支持,以及商业使用的爆炸式发展。 14 | 四年前的 Pro Git 对此一无所知。 15 | 新版本的主要目标之一就是涉及 Git 社区中那些所有新的前沿领域。 16 | 17 | 使用 Git 的开源社区也呈现出爆炸式的发展。 18 | 大概在五年前吧,我坐下来写这本书时(写完第一个版本花了我不少时间),我开始在一个知名度极小的开发 Git 托管网站的公司工作,这家公司就是 GitHub。 19 | 本书出版时大概有几千人在使用 GitHub 网站,而为其工作的只有我们四个人。 20 | 在我写这篇介绍时,GitHub 宣布我们托管了 1000 万个项目、拥有大概 500 万注册开发者账户与大概 230 名员工。 21 | 爱它也好,恨它也罢,当我坐下来写第一版时,GitHub 以一种意想不到的方式猛烈地改变了一大批开源社区。 22 | 23 | 我在 Pro Git 的原始版本中写了一节我并不是很满意的内容,是作为和提供 Git 托管服务相关的例子的 GitHub。 24 | 我在书里写的东西本质上都是和社区有关的,但是又不得不讨论到我的公司,这点我不喜欢。 25 | 虽然我还是不喜欢这种利益冲突,但 GitHub 在 Git 社区的重要性是不能回避的。 26 | 我已经决定将本书中关于 GitHub 的部分转变为深度介绍 GitHub 是什么以及如何高效地使用它,而不再是作为一个 Git 托管的例子。 27 | 如果你正学习如何使用 Git,那么了解如何使用 GitHub 将会帮助你加入到一个巨大的社区中。不论你决定为自己的代码使用哪一个 Git 托管服务,这都很有价值。 28 | 29 | 自从上次出版以来另一个重大变革是 Git 网络传输 HTTP 协议的开发与崛起。书中的大多数例子都已经从 SSH 切换到 HTTP,因为它更简单。 30 | 31 | 在过去这几年看到 Git 从一个相对无名的版本管理系统成长为商业与开源版本管理的事实标准是令人吃惊的。我很高兴 Pro Git 做得很好并已经成为市场上几本既成功又完全开源的技术书籍之一。 32 | 33 | 我希望你能享受这个升级版的 Pro Git。 34 | -------------------------------------------------------------------------------- /ch09-git-and-other-systems.asc: -------------------------------------------------------------------------------- 1 | [[ch09-git-and-other-systems]] 2 | == Git 与其他系统 3 | 4 | 现实并不总是尽如人意。 5 | 通常,你不能立刻就把接触到的每一个项目都切换到 Git。 6 | 有时候你被困在使用其他 VCS 的项目中,却希望使用 Git。 7 | 在本章的第一部分我们将会了解到,怎样在你的那些托管在不同系统的项目上使用 Git 客户端。 8 | 9 | 在某些时候,你可能想要将已有项目转换到 Git。 10 | 本章的第二部分涵盖了从几个特定系统将你的项目迁移至 Git 的方法,即使没有预先构建好的导入工具,我们也有办法手动导入。 11 | 12 | === 作为客户端的 Git 13 | 14 | (((Git as a client))) 15 | Git 为开发者提供了如此优秀的体验,许多人已经找到了在他们的工作站上使用 Git 的方法,即使他们团队其余的人使用的是完全不同的 VCS。 16 | 有许多这种可用的适配器,它们被叫做“桥接”。 17 | 下面我们将要介绍几个很可能会在实际中用到的桥接。 18 | 19 | include::book/09-git-and-other-scms/sections/client-svn.asc[] 20 | 21 | include::book/09-git-and-other-scms/sections/client-hg.asc[] 22 | 23 | include::book/09-git-and-other-scms/sections/client-p4.asc[] 24 | 25 | [[_migrating]] 26 | === 迁移到 Git 27 | 28 | (((Migrating to Git))) 29 | 如果你现在有一个正在使用其他 VCS 的代码库,但是你已经决定开始使用 Git,必须通过某种方式将你的项目迁移至 Git。 30 | 这一部分会介绍一些通用系统的导入器,然后演示如何开发你自己定制的导入器。 31 | 你将会学习如何从几个大型专业应用的 SCM 系统中导入数据,不仅因为它们是大多数想要转换的用户正在使用的系统,也因为获取针对它们的高质量工具很容易。 32 | 33 | include::book/09-git-and-other-scms/sections/import-svn.asc[] 34 | 35 | include::book/09-git-and-other-scms/sections/import-hg.asc[] 36 | 37 | include::book/09-git-and-other-scms/sections/import-p4.asc[] 38 | 39 | include::book/09-git-and-other-scms/sections/import-custom.asc[] 40 | 41 | === 总结 42 | 43 | 你会觉得将 Git 作为其他版本控制系统的客户端,或者在数据无损的情况下将几乎任何一个现有的仓库导入到 Git,都是一件很惬意的事。 44 | 在下一章,我们将要讲解 Git 的原始内部数据,如果需要的话你就可以加工每一个字节。 45 | -------------------------------------------------------------------------------- /book/10-git-internals/sections/plumbing-porcelain.asc: -------------------------------------------------------------------------------- 1 | [[_plumbing_porcelain]] 2 | === 底层命令与上层命令 3 | 4 | 本书主要涵盖了 `checkout`、`branch`、`remote` 等约 30 个 Git 的子命令。 5 | 然而,由于 Git 最初是一套面向版本控制系统的工具集,而不是一个完整的、用户友好的版本控制系统, 6 | 所以它还包含了一部分用于完成底层工作的子命令。 7 | 这些命令被设计成能以 UNIX 命令行的风格连接在一起,抑或藉由脚本调用,来完成工作。 8 | 这部分命令一般被称作“底层(plumbing)”命令,而那些更友好的命令则被称作“上层(porcelain)”命令。 9 | 10 | 你或许已经注意到了,本书前九章专注于探讨上层命令。 11 | 然而在本章中,我们将主要面对底层命令。 12 | 因为,底层命令得以让你窥探 Git 内部的工作机制,也有助于说明 Git 是如何完成工作的,以及它为何如此运作。 13 | 多数底层命令并不面向最终用户:它们更适合作为新工具的组件和自定义脚本的组成部分。 14 | 15 | 当在一个新目录或已有目录执行 `git init` 时,Git 会创建一个 `.git` 目录。 16 | 这个目录包含了几乎所有 Git 存储和操作的东西。 17 | 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。 18 | 本章探讨的所有内容,均位于这个目录内。 19 | 新初始化的 `.git` 目录的典型结构如下: 20 | 21 | [source,console] 22 | ---- 23 | $ ls -F1 24 | config 25 | description 26 | HEAD 27 | hooks/ 28 | info/ 29 | objects/ 30 | refs/ 31 | ---- 32 | 33 | 随着 Git 版本的不同,该目录下可能还会包含其他内容。 34 | 不过对于一个全新的 `git init` 版本库,这将是你看到的默认结构。 35 | `description` 文件仅供 GitWeb 程序使用,我们无需关心。 36 | `config` 文件包含项目特有的配置选项。 37 | `info` 目录包含一个全局性排除(global exclude)文件(((excludes))), 38 | 用以放置那些不希望被记录在 `.gitignore` 文件中的忽略模式(ignored patterns)。 39 | `hooks` 目录包含客户端或服务端的钩子脚本(hook scripts), 40 | 在 <> 中这部分话题已被详细探讨过。 41 | 42 | 剩下的四个条目很重要:`HEAD` 文件、(尚待创建的)`index` 文件,和 `objects` 目录、`refs` 目录。 43 | 它们都是 Git 的核心组成部分。 44 | `objects` 目录存储所有数据内容;`refs` 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针; 45 | `HEAD` 文件指向目前被检出的分支;`index` 文件保存暂存区信息。 46 | 我们将详细地逐一检视这四部分,来理解 Git 是如何运转的。 47 | -------------------------------------------------------------------------------- /ch10-git-internals.asc: -------------------------------------------------------------------------------- 1 | [[ch10-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 | 17 | include::book/10-git-internals/sections/plumbing-porcelain.asc[] 18 | 19 | include::book/10-git-internals/sections/objects.asc[] 20 | 21 | include::book/10-git-internals/sections/refs.asc[] 22 | 23 | include::book/10-git-internals/sections/packfiles.asc[] 24 | 25 | include::book/10-git-internals/sections/refspec.asc[] 26 | 27 | include::book/10-git-internals/sections/transfer-protocols.asc[] 28 | 29 | include::book/10-git-internals/sections/maintenance.asc[] 30 | 31 | include::book/10-git-internals/sections/environment.asc[] 32 | 33 | === 总结 34 | 35 | 现在,你应该相当了解 Git 在背后都做了些什么工作,并且在一定程度上也知道了 Git 是如何实现的。 36 | 本章讨论了很多底层命令,这些命令比我们在本书其余部分学到的高层命令来得更原始,也更简洁。 37 | 从底层了解 Git 的工作原理有助于更好地理解 Git 在内部是如何运作的,也方便你能够针对特定的工作流写出自己的工具和脚本。 38 | 39 | 作为一套内容寻址文件系统,Git 不仅仅是一个版本控制系统,它同时是一个非常强大且易用的工具。 40 | 我们希望你可以借助新学到的 Git 内部原理相关知识来实现出自己的应用,并且以更高级、更得心应手的方式来驾驭 Git。 41 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/bash.asc: -------------------------------------------------------------------------------- 1 | === Bash 中的 Git 2 | 3 | (((bash)))(((tab completion, bash)))(((shell prompts, bash))) 4 | 如果你是一名 Bash 用户,你可以从中发掘出一些 Shell 的特性,让你在使用 Git 时更加随心所欲。 5 | 实际上 Git 附带了几个 Shell 的插件,但是这些插件并不是默认打开的。 6 | 7 | 首先,你需要从你使用的 Git 发行版的源代码中获得一份自动补全文件的拷贝。 8 | 输入 `git version` 检查版本,然后使用 `git checkout tags/vX.Y.Z`,其中 `vX.Y.Z` 对应于你正在使用的 Git 版本。 9 | 将这个 `contrib/completion/git-completion.bash` 文件复制到一个相对便捷的目录,例如你的 Home 目录,并且将它的路径添加到 `.bashrc` 中: 10 | 11 | [source,console] 12 | ----- 13 | . ~/git-completion.bash 14 | ----- 15 | 16 | 做完这些之后,请将你当前的目录切换到某一个 Git 仓库,并且输入: 17 | 18 | [source,console] 19 | ---- 20 | $ git chec 21 | ---- 22 | 23 | ……此时 Bash 将会把上面的命令自动补全为 `git checkout`。 24 | 在适当的情况下,这项功能适用于 Git 所有的子命令、命令行参数、以及远程仓库与引用名。 25 | 26 | 这项功能也可以用于你自己定义的提示符(`prompt`),显示当前目录下 Git 仓库的信息。 27 | 根据你的需要,这个信息可以简单或复杂,这里通常有大多数人想要的几个关键信息,比如当前分支信息和当前工作目录的状态信息。 28 | 要添加你自己的提示符(`prompt`),只需从 Git 源版本库复制 `contrib/completion/git-prompt.sh` 文件到你的 Home 目录(或其他便于你访问与管理的目录), 并在 `.bashrc` 里添加这个文件路径,类似于下面这样: 29 | 30 | [source,console] 31 | ----- 32 | . ~/git-prompt.sh 33 | export GIT_PS1_SHOWDIRTYSTATE=1 34 | export PS1='\w$(__git_ps1 " (%s)")\$ ' 35 | ----- 36 | 37 | `\w` 表示打印当前工作目录,`\$` 打印 `$` 部分的提示符(`prompt`),`__git_ps1 " (%s)"` 表示通过格式化参数符(`%s`)调用`git-prompt.sh`脚本中提供的函数。 38 | 因为有了这个自定义提示符,现在你的 `Bash` 提示符(`prompt`)在 Git 仓库的任何子目录中都将显示成这样: 39 | 40 | .自定义的 `bash` 提示符(`prompt`). 41 | image::images/git-bash.png[自定义的 `bash` 提示符(`prompt`).] 42 | 43 | 这两个脚本都提供了很有帮助的文档;浏览 `git-completion.bash` 和 `git-prompt.sh` 的内容以获得更多信息。 44 | -------------------------------------------------------------------------------- /README.asc: -------------------------------------------------------------------------------- 1 | image::https://travis-ci.org/progit/progit2-zh.svg?branch=master[] 2 | = Pro Git,第二版,简体中文 3 | 4 | **翻译、校对、修改前请阅读 link:TRANSLATION_NOTES.asc[翻译规范]!** 5 | 6 | 欢迎阅读 Pro Git 第二版。 7 | 8 | 你可以访问 https://git-scm.com/book 在线阅读本书。 9 | 10 | 与第一版类似,Pro Git 第二版以知识共享协议开源。 11 | 12 | 自第一版开源以来,许多事情都发生了变化。 13 | 首先,我们将本书的文本由 Markdown 迁移至 Asciidoc。 14 | 15 | 我们还在独立的仓库中进行翻译,而不是在英文仓库的子目录中。 16 | 查看 link:CONTRIBUTING.md[贡献文档] 了解更多信息。 17 | 18 | == 如何生成本书 19 | 20 | 你可以用 Asciidoctor 手动生成电子书文件。 21 | 如果你运行下面的命令,你 _可能_ 实际上获得 HTML、Epub、Mobi 和 PDF 输出文件: 22 | 23 | ---- 24 | $ bundle install 25 | $ asciidoctor-pdf-cjk-kai_gen_gothic-install 26 | $ bundle exec rake book:build 27 | Converting to HTML... 28 | -- HTML output at progit.html 29 | Converting to EPub... 30 | -- Epub output at progit.epub 31 | Converting to Mobi (kf8)... 32 | -- Mobi output at progit.mobi 33 | Converting to PDF... 34 | -- PDF output at progit.pdf 35 | ---- 36 | 37 | 你可以只生成一种支持的格式( HTML、EPUB、mobi、或 PDF )。 38 | 使用以下命令之一: 39 | 40 | 生成 HTML 图书: 41 | 42 | ---- 43 | $ bundle exec rake book:build_html 44 | ---- 45 | 46 | 生成 EPUB 图书: 47 | 48 | ---- 49 | $ bundle exec rake book:build_epub 50 | ---- 51 | 52 | 生成 mobi 图书: 53 | 54 | ---- 55 | $ bundle exec rake book:build_mobi 56 | ---- 57 | 58 | 生成 PDF 图书: 59 | 60 | ---- 61 | $ bundle exec rake book:build_pdf 62 | ---- 63 | 64 | ## 发起一个 Issue 65 | 66 | 在发起一个 Issue 前,请在 bug 跟踪系统中搜索是否已有类似的问题。 67 | 68 | 此外,如果该问题是在 git-scm.com 网站上发现的,请再次确认 pdf 版本中是否仍有此问题。 69 | 该问题可能已被修复,但修改内容尚未部署。 70 | 71 | == 贡献 72 | 73 | 如果你想要帮助修改或者贡献翻译,查看 link:CONTRIBUTING.md[贡献者指南]。 74 | -------------------------------------------------------------------------------- /ch04-git-on-the-server.asc: -------------------------------------------------------------------------------- 1 | [[ch04-git-on-the-server]] 2 | == 服务器上的 Git 3 | 4 | (((serving repositories))) 5 | 到目前为止,你应该已经有办法使用 Git 来完成日常工作。 6 | 然而,为了使用 Git 协作功能,你还需要有远程的 Git 仓库。 7 | 尽管在技术上你可以从个人仓库进行推送(push)和拉取(pull)来修改内容,但不鼓励使用这种方法,因为一不留心就很容易弄混其他人的进度。 8 | 此外,你希望你的合作者们即使在你的电脑未联机时亦能存取仓库 — 拥有一个更可靠的公用仓库十分有用。 9 | 因此,与他人合作的最佳方法即是建立一个你与合作者们都有权利访问,且可从那里推送和拉取资料的共用仓库。 10 | 11 | 架设一台 Git 服务器并不难。 12 | 首先,选择你希望服务器使用的通讯协议。 13 | 在本章第一节将介绍可用的协议以及各自优缺点。 14 | 下面一节将解释使用那些协议的典型设置及如何在你的服务器上运行。 15 | 最后,如果你不介意托管你的代码在其他人的服务器,且不想经历设置与维护自己服务器的麻烦,可以试试我们介绍的几个仓库托管服务。 16 | 17 | 如果你对架设自己的服务器没兴趣,可以跳到本章最后一节去看看如何申请一个代码托管服务的帐户然后继续下一章,我们会在那里讨论分布式源码控制环境的林林总总。 18 | 19 | 一个远程仓库通常只是一个裸仓库(bare repository)——即一个没有当前工作目录的仓库。 20 | 因为该仓库仅仅作为合作媒介,不需要从磁盘检查快照;存放的只有 Git 的资料。 21 | 简单的说,裸仓库就是你工程目录内的 `.git` 子目录内容,不包含其他资料。 22 | 23 | include::book/04-git-server/sections/protocols.asc[] 24 | 25 | include::book/04-git-server/sections/git-on-a-server.asc[] 26 | 27 | include::book/04-git-server/sections/generating-ssh-key.asc[] 28 | 29 | include::book/04-git-server/sections/setting-up-server.asc[] 30 | 31 | include::book/04-git-server/sections/git-daemon.asc[] 32 | 33 | include::book/04-git-server/sections/smart-http.asc[] 34 | 35 | include::book/04-git-server/sections/gitweb.asc[] 36 | 37 | include::book/04-git-server/sections/gitlab.asc[] 38 | 39 | include::book/04-git-server/sections/hosted.asc[] 40 | 41 | === 总结 42 | 43 | 你有多种远程存取 Git 仓库的选择便于与其他人合作或是分享你的工作。 44 | 45 | 运行你自己的服务器将有许多权限且允许你运行该服务于你自己的防火墙内,但如此通常需要耗费你大量的时间去设置与维护服务器。 46 | 如果你放置你的资料于托管服务器内,可轻易的设置与维护;无论如何,你必须被允许在其他服务器上保存你的代码,而该行为在某些组织是不允许的。 47 | 这将直截了当的决定哪个作法或组合的方式较适合你或你的组织。 48 | -------------------------------------------------------------------------------- /book/02-git-basics/sections/aliases.asc: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /book/01-introduction/sections/help.asc: -------------------------------------------------------------------------------- 1 | [[_git_help]] 2 | === 获取帮助 3 | 4 | 若你使用 Git 时需要获取帮助,有三种等价的方法可以找到 Git 命令的综合手册(manpage): 5 | 6 | [source,console] 7 | ---- 8 | $ git help 9 | $ git --help 10 | $ man git- 11 | ---- 12 | 13 | 例如,要想获得 `git config` 命令的手册,执行 (((git commands, help))) 14 | 15 | [source,console] 16 | ---- 17 | $ git help config 18 | ---- 19 | 20 | 这些命令很棒,因为你随时随地可以使用而无需联网。 21 | 如果你觉得手册或者本书的内容还不够用,你可以尝试在 Freenode IRC 服务器 https://freenode.net[] 上的 `#git` 或 `#github` 频道寻求帮助。 22 | 这些频道经常有上百人在线,他们都精通 Git 并且乐于助人。(((IRC))) 23 | 24 | 此外,如果你不需要全面的手册,只需要可用选项的快速参考,那么可以用 `-h` 选项获得更简明的 ``help'' 输出: 25 | 26 | [source,console] 27 | ---- 28 | $ git add -h 29 | usage: git add [] [--] ... 30 | 31 | -n, --dry-run dry run 32 | -v, --verbose be verbose 33 | 34 | -i, --interactive interactive picking 35 | -p, --patch select hunks interactively 36 | -e, --edit edit current diff and apply 37 | -f, --force allow adding otherwise ignored files 38 | -u, --update update tracked files 39 | --renormalize renormalize EOL of tracked files (implies -u) 40 | -N, --intent-to-add record only the fact that the path will be added later 41 | -A, --all add changes from all tracked and untracked files 42 | --ignore-removal ignore paths removed in the working tree (same as --no-all) 43 | --refresh don't add, only refresh the index 44 | --ignore-errors just skip files which cannot be added because of errors 45 | --ignore-missing check if - even missing - files are ignored in dry run 46 | --chmod (+|-)x override the executable bit of the listed files 47 | ---- 48 | 49 | -------------------------------------------------------------------------------- /book/04-git-server/sections/git-daemon.asc: -------------------------------------------------------------------------------- 1 | === Git 守护进程 2 | 3 | (((serving repositories, git protocol))) 4 | 接下来我们将通过 “Git” 协议建立一个基于守护进程的仓库。 5 | 对于快速且无需授权的 Git 数据访问,这是一个理想之选。 6 | 请注意,因为其不包含授权服务,任何通过该协议管理的内容将在其网络上公开。 7 | 8 | 如果运行在防火墙之外的服务器上,它应该只对那些公开的只读项目服务。 9 | 如果运行在防火墙之内的服务器上,它可用于支撑大量参与人员或自动系统 10 | (用于持续集成或编译的主机)只读访问的项目,这样可以省去逐一配置 SSH 公钥的麻烦。 11 | 12 | 无论何时,该 Git 协议都是相对容易设定的。 13 | 通常,你只需要以守护进程的形式运行该命令:(((git commands, daemon))) 14 | 15 | [source,console] 16 | ---- 17 | $ git daemon --reuseaddr --base-path=/srv/git/ /srv/git/ 18 | ---- 19 | 20 | `--reuseaddr` 选项允许服务器在无需等待旧连接超时的情况下重启,而 21 | `--base-path` 选项允许用户在未完全指定路径的条件下克隆项目, 22 | 结尾的路径将告诉 Git 守护进程从何处寻找仓库来导出。 23 | 如果有防火墙正在运行,你需要开放端口 9418 的通信权限。 24 | 25 | 你可以通过许多方式将该进程以守护进程的方式运行,这主要取决于你所使用的操作系统。 26 | 27 | 由于在现代的 Linux 发行版中,`systemd` 是最常见的初始化系统,因此你可以用它来达到此目的。 28 | 只要在 `/etc/systemd/system/git-daemon.service` 中放一个文件即可,其内容如下: 29 | 30 | [source,console] 31 | ---- 32 | [Unit] 33 | Description=Start Git Daemon 34 | 35 | [Service] 36 | ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/ 37 | 38 | Restart=always 39 | RestartSec=500ms 40 | 41 | StandardOutput=syslog 42 | StandardError=syslog 43 | SyslogIdentifier=git-daemon 44 | 45 | User=git 46 | Group=git 47 | 48 | [Install] 49 | WantedBy=multi-user.target 50 | ---- 51 | 52 | 你可能会注意这里以 `git` 启动的 Git 驻留程序同时使用了 Group 和 User 权限。 53 | 按需修改它并确保提供的用户在此系统上。此外,请确保 Git 二进制文件位于 54 | `/usr/bin/git`,必要时可修改此路径。 55 | 56 | 最后,你需要运行 `systemctl enable git-daemon` 以让它在系统启动时自动运行, 57 | 这样也能让它通过 `systemctl start git-daemon` 启动,通过 `systemctl stop git-daemon` 停止。 58 | 59 | 在其他系统中,你可以使用 `sysvinit` 系统中的 `xinetd` 脚本,或者另外的方式来实现——只要你能够将其命令守护进程化并实现监控。 60 | 61 | 接下来,你需要告诉 Git 哪些仓库允许基于服务器的无授权访问。 62 | 你可以在每个仓库下创建一个名为 `git-daemon-export-ok` 的文件来实现。 63 | 64 | [source,console] 65 | ---- 66 | $ cd /path/to/project.git 67 | $ touch git-daemon-export-ok 68 | ---- 69 | 70 | 该文件将允许 Git 提供无需授权的项目访问服务。 71 | -------------------------------------------------------------------------------- /book/03-git-branching/sections/branch-management.asc: -------------------------------------------------------------------------------- 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 | 63 | [TIP] 64 | ==== 65 | 上面描述的选项 `--merged` 和 `--no-merged` 会在没有给定提交或分支名作为参数时, 66 | 分别列出已合并或未合并到 *当前* 分支的分支。 67 | 68 | 你总是可以提供一个附加的参数来查看其它分支的合并状态而不必检出它们。 69 | 例如,尚未合并到 `master` 分支的有哪些? 70 | [source,console] 71 | ---- 72 | $ git checkout testing 73 | $ git branch --no-merged master 74 | topicA 75 | featureB 76 | ---- 77 | ==== 78 | -------------------------------------------------------------------------------- /theme/epub/epub.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /theme/html/html.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /theme/mobi/mobi.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/zsh.asc: -------------------------------------------------------------------------------- 1 | === Zsh 中的 Git 2 | 3 | (((zsh)))(((tab completion, zsh)))(((shell prompts, zsh))) 4 | Zsh 还为 Git 提供了一个 Tab 补全库。 5 | 想要使用它,只需在你的 `.zshrc` 中执行 `autoload -Uz compinit && compinit` 即可。 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 提供了一个从版本控制系统中获取信息的框架,叫做 `vcs_info` 。 23 | 把如下代码添加至你的 `~/.zshrc` 文件中,就可以在右侧显示分支名称: 24 | 25 | [source,console] 26 | ---- 27 | autoload -Uz vcs_info 28 | precmd_vcs_info() { vcs_info } 29 | precmd_functions+=( precmd_vcs_info ) 30 | setopt prompt_subst 31 | RPROMPT=\$vcs_info_msg_0_ 32 | # PROMPT=\$vcs_info_msg_0_'%# ' 33 | zstyle ':vcs_info:git:*' formats '%b' 34 | ---- 35 | 36 | 当你的命令行位于一个 Git 仓库目录时,在任何时候,都可以在命令行窗口右侧显示当前分支。 37 | (当然也可以在左侧显示,只需把上面 `PROMPT` 的注释去掉即可。) 38 | 它看起来像这样: 39 | 40 | .自定义 `zsh` 提示符. 41 | image::images/zsh-prompt.png[自定义 `zsh` 提示符.] 42 | 43 | 关于 `vcs_info` 的更多信息,可参见 `zshcontrib(1)` 手册页面中对应的文档,或访问 http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Version-Control-Information[] 在线浏览。 44 | 45 | 比起 `vcs_info` 而言,你可能更偏好提供了 Git 的命令提示符定制脚本 `git-prompt.sh`;更多信息见 https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh[]。 46 | `git-prompt.sh` 同时兼容 Bash 和 Zsh。 47 | 48 | Zsh 本身已足够强大,但还有一些专门为它打造的完整框架,使它更加完善。 49 | 其中之一名为 "oh-my-zsh",你可以在 https://github.com/robbyrussell/oh-my-zsh[] 找到它。 50 | oh-my-zsh 的扩展系统包含强大的 Git Tab 补全功能,且许多提示符 "主题" 可以展示版本控制数据。 51 | <> 只是可以其中一个可以通过该系统实现的例子。 52 | 53 | [[oh_my_zsh_git]] 54 | .一个 oh-my-zsh 主题的示例. 55 | image::images/zsh-oh-my.png[一个 oh-my-zsh 主题的示例] 56 | -------------------------------------------------------------------------------- /book/introduction.asc: -------------------------------------------------------------------------------- 1 | [preface] 2 | == 引言 3 | 4 | 你将花费你生命中的若干小时来阅读有关 Git 的相关内容。 5 | 让我们用几分钟时间来介绍下我们将给你讲解的内容。 6 | 下面是本书正文十章和附录三章的快速总结。 7 | 8 | 在 *第一章* ,我们将介绍版本控制系统(VCSs)和 Git 的基本概念——不涉及技术内容,仅仅是什么是 Git, 9 | 为什么它会成为 VCSs 大家庭中的一员,它与其它 VCSs 的区别,以及为什么那么多人都在使用 Git。 10 | 然后,我们将介绍如何下载 Git 以及如果你的系统没有安装 Git,如何为第一次运行做准备。 11 | 12 | 在 *第二章* ,我们将阐述 Git 的基本使用——包含你在使用 Git 时可能遇到的 80% 的情形。 13 | 通过阅读本章,你应该能够克隆仓库、查看项目历史、修改文件和贡献更改。 14 | 如果本书在此刻自燃,你应该已经能够使用已经学到的漂亮有用的 Git 知识获取到另外一份拷贝。 15 | 16 | *第三章* 关注于 Git 的分支模型。分支模型通常被认为是 Git 的杀手级特性。 17 | 这里,你将学习到究竟是什么让 Git 与众不同。学习完本章,你可能需要一段时间来思考, 18 | 在 Git 分支成为你的生活的一部分之前,你到底是如何生活的。 19 | 20 | *第四章* 关注于服务器端的 Git。本章面向那些希望在你自己的组织或个人服务器搭建用于合作的 Git 的读者。 21 | 如果你希望让别人处理这些事务,我们也会探讨一些托管选项。 22 | 23 | *第五章* 将阐述多种分布式工作流的细节,以及如何使用 Git 实现它们。 24 | 学习完本章,你应该能够在多个远程仓库之间游刃有余,通过电子邮件使用 Git, 25 | 熟练地处理多个远程分支和合作者贡献的补丁。 26 | 27 | *第六章* 介绍 GitHub 托管服务以及深层次的工具。我们将涵盖注册与账户管理, 28 | 创建和使用 Git 仓库,贡献项目的普通工作流以及接受他人的贡献,GitHub 29 | 的可编程接口和那些能够让你的生活变得更简单的小技巧。 30 | 31 | *第七章* 关于 Git 的高级命令。你将学习到一些高级主题,诸如掌握可怕的“reset”命令, 32 | 使用二分搜索识别错误,编辑历史,细节版本选择等等。本章的介绍将丰富你的 33 | Git 知识,让你成为一个真正的大师。 34 | 35 | *第八章* 关于 Git 环境的自定义配置,包括设置用于增强或促进自定义策略的钩子脚本, 36 | 以及按照你所需要的方式进行工作的环境配置。我们还会介绍构建你自己的脚本集,以增强自定义提交策略。 37 | 38 | *第九章* 对比 Git 和其它 VCSs,包括在 Subversion(SVN)的世界使用 Git 以及从其它 VCSs 迁移到 Git。 39 | 很多组织仍在使用 SVN,并且也没有计划改变,此时,你将了解到 Git 不可思议的能力——本章将展示, 40 | 在你不得不使用 SVN 服务器的时候如何协同合作。我们还将介绍如何从不同系统导入项目, 41 | 以便你能够全身心投入 Git 的怀抱。 42 | 43 | *第十章* 深入 Git 隐晦而漂亮的实现细节。现在,你已经知道所有有关 Git 的知识, 44 | 能够熟练运用 Git 的强大优雅的功能。接下来,你可以继续学习 Git 如何存储对象、 45 | Git 的对象模型是怎样的、打包文件的细节、服务器协议等更多知识。 46 | 本书自始至终都将引用本章的内容,以便你能够在当时就可以深入了解。 47 | 但是,如果你像我们一样希望深入学习技术细节,你可能想先阅读第十章。我们将选择权交给你。 48 | 49 | 在 *附录 A* ,我们学习多个在特定环境中使用 Git 的实例。 50 | 我们涵盖了许多不同的 GUI 和 IDE 编程环境,你可能会想在这些环境中使用 Git,以及你可以使用哪些环境。 51 | 如果你想在 shell、IDE 或文本编辑器中使用 Git,请阅读本章。 52 | 53 | 在 *附录 B* ,我们探讨通过类似 libgit2 和 JGit 的工具编写 Git 脚本、扩展 Git。 54 | 如果你对编写复杂、快速的自定义工具感兴趣,需要了解 Git 的底层访问,本章就是你所需要了解的。 55 | 56 | 最后在 *附录 C* ,我们一次性浏览 Git 的所有主要命令,复习在本书中介绍的内容, 57 | 回忆我们能够使用这些命令做什么。如果你需要知道本书中我们使用了哪些特定 Git 命令,你可以在这里查阅。 58 | 59 | 下面让我们开始吧。 60 | -------------------------------------------------------------------------------- /book/06-github/sections/4-managing-organization.asc: -------------------------------------------------------------------------------- 1 | [[ch06-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 | -------------------------------------------------------------------------------- /book/01-introduction/sections/about-version-control.asc: -------------------------------------------------------------------------------- 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 | https://www.gnu.org/software/rcs/[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 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 55 | 而是把代码仓库完整地镜像下来,包括完整的历史记录。 56 | 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 57 | 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。 58 | 59 | .分布式版本控制. 60 | image::images/distributed.png[分布式版本控制图解] 61 | 62 | 更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 63 | 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。 64 | -------------------------------------------------------------------------------- /theme/pdf/pdf.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /book/04-git-server/sections/generating-ssh-key.asc: -------------------------------------------------------------------------------- 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` 程序来创建它们。 23 | 在 Linux/macOS 系统中,`ssh-keygen` 随 SSH 软件包提供;在 Windows 上,该程序包含于 MSysGit 软件包中。 24 | 25 | [source,console] 26 | ---- 27 | $ ssh-keygen -o 28 | Generating public/private rsa key pair. 29 | Enter file in which to save the key (/home/schacon/.ssh/id_rsa): 30 | Created directory '/home/schacon/.ssh'. 31 | Enter passphrase (empty for no passphrase): 32 | Enter same passphrase again: 33 | Your identification has been saved in /home/schacon/.ssh/id_rsa. 34 | Your public key has been saved in /home/schacon/.ssh/id_rsa.pub. 35 | The key fingerprint is: 36 | d0:82:24:8e:d7:f1:bb:9b:33:53:96:93:49:da:9b:e3 schacon@mylaptop.local 37 | ---- 38 | 39 | 首先 `ssh-keygen` 会确认密钥的存储位置(默认是 `.ssh/id_rsa`),然后它会要求你输入两次密钥口令。 40 | 如果你不想在使用密钥时输入口令,将其留空即可。 41 | 然而,如果你使用了密码,那么请确保添加了 `-o` 选项,它会以比默认格式更能抗暴力破解的格式保存私钥。 42 | 你也可以用 `ssh-agent` 工具来避免每次都要输入密码。 43 | 44 | 现在,进行了上述操作的用户需要将各自的公钥发送给任意一个 Git 服务器管理员 45 | (假设服务器正在使用基于公钥的 SSH 验证设置)。 46 | 他们所要做的就是复制各自的 `.pub` 文件内容,并将其通过邮件发送。 47 | 公钥看起来是这样的: 48 | 49 | [source,console] 50 | ---- 51 | $ cat ~/.ssh/id_rsa.pub 52 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU 53 | GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 54 | Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA 55 | t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En 56 | mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx 57 | NrRFi9wrf+M7Q== schacon@mylaptop.local 58 | ---- 59 | 60 | 关于在多种操作系统中生成 SSH 密钥的更深入教程,请参阅 GitHub 的 SSH 密钥指南 61 | https://docs.github.com/cn/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent[]。 62 | -------------------------------------------------------------------------------- /book/04-git-server/sections/gitweb.asc: -------------------------------------------------------------------------------- 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 如何展示你的项目,并且在服务器上安装了轻量级 Web 服务器比如 `lighttpd` 或 `webrick`, 12 | Git 提供了一个命令来让你启动一个临时的服务器。 13 | 在 Linux 系统的电脑上,`lighttpd` 通常已经安装了,所以你只需要在项目目录里执行 `git instaweb` 命令即可。 14 | 如果你使用 Mac 系统, Mac OS X Leopard 系统已经预安装了 Ruby,所以 `webrick` 或许是你最好的选择。 15 | 如果不想使用 lighttpd 启动 `instaweb` 命令,你需要在执行时加入 `--httpd` 参数。(((git commands, instaweb))) 16 | 17 | [source,console] 18 | ---- 19 | $ git instaweb --httpd=webrick 20 | [2009-02-21 10:02:21] INFO WEBrick 1.3.1 21 | [2009-02-21 10:02:21] INFO ruby 1.8.6 (2008-03-03) [universal-darwin9.0] 22 | ---- 23 | 24 | 这个命令启动了一个监听 1234 端口的 HTTP 服务器,并且自动打开了浏览器。 25 | 这对你来说十分方便。 26 | 当你已经完成了工作并想关闭这个服务器,你可以执行同一个命令,并加上 `--stop` 选项: 27 | 28 | [source,console] 29 | ---- 30 | $ git instaweb --httpd=webrick --stop 31 | ---- 32 | 33 | 如果你现在想为你的团队或你托管的开源项目持续的运行这个页面,你需要通过普通的 Web 服务器来设置 CGI 脚本。 34 | 一些 Linux 发行版的软件库有 `gitweb` 包,可以通过 `apt` 或 `dnf` 来安装,你可以先试试。 35 | 接下来我们来快速的了解一下如何手动安装 GitWeb。 36 | 首先,你需要获得 Git 的源代码,它包含了 GitWeb ,并可以生成自定义的 CGI 脚本: 37 | 38 | [source,console] 39 | ---- 40 | $ git clone git://git.kernel.org/pub/scm/git/git.git 41 | $ cd git/ 42 | $ make GITWEB_PROJECTROOT="/srv/git" prefix=/usr gitweb 43 | SUBDIR gitweb 44 | SUBDIR ../ 45 | make[2]: `GIT-VERSION-FILE' is up to date. 46 | GEN gitweb.cgi 47 | GEN static/gitweb.js 48 | $ sudo cp -Rf gitweb /var/www/ 49 | ---- 50 | 51 | 需要注意的是,你需要在命令中指定 `GITWEB_PROJECTROOT` 变量来让程序知道你的 Git 版本库的位置。 52 | 现在,你需要在 Apache 中使用这个 CGI 脚本,你需要为此添加一个虚拟主机: 53 | 54 | [source,console] 55 | ---- 56 | 57 | ServerName gitserver 58 | DocumentRoot /var/www/gitweb 59 | 60 | Options +ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch 61 | AllowOverride All 62 | order allow,deny 63 | Allow from all 64 | AddHandler cgi-script cgi 65 | DirectoryIndex gitweb.cgi 66 | 67 | 68 | ---- 69 | 70 | 再次提醒,GitWeb 可以通过任何一个支持 CGI 或 Perl 的网络服务器架设;如果你需要的话,架设起来应该不会很困难。 71 | 现在,你可以访问 `http://gitserver/` 在线查看你的版本库。 72 | -------------------------------------------------------------------------------- /atlas.json: -------------------------------------------------------------------------------- 1 | { 2 | "branch": "master", 3 | "files": [ 4 | "book/cover.html", 5 | "LICENSE.asc", 6 | "book/preface.asc", 7 | "book/contributors.asc", 8 | "book/introduction.asc", 9 | "book/toc.asc", 10 | "book/01-introduction/1-introduction.asc", 11 | "book/02-git-basics/1-git-basics.asc", 12 | "book/03-git-branching/1-git-branching.asc", 13 | "book/04-git-server/1-git-server.asc", 14 | "book/05-distributed-git/1-distributed-git.asc", 15 | "book/06-github/1-github.asc", 16 | "book/07-git-tools/1-git-tools.asc", 17 | "book/08-customizing-git/1-customizing-git.asc", 18 | "book/09-git-and-other-scms/1-git-and-other-scms.asc", 19 | "book/10-git-internals/1-git-internals.asc", 20 | "book/A-git-in-other-environments/1-git-other-environments.asc", 21 | "book/B-embedding-git/1-embedding-git.asc", 22 | "book/C-git-commands/1-git-commands.asc", 23 | "book/index.asc" 24 | ], 25 | "formats": { 26 | "pdf": { 27 | "version": "web", 28 | "index": true, 29 | "toc": true, 30 | "syntaxhighlighting": true, 31 | "show_comments": false 32 | }, 33 | "epub": { 34 | "index": true, 35 | "toc": true, 36 | "epubcheck": true, 37 | "embedded_fonts": [ 38 | "fonts/DejaVuSerif.otf", 39 | "fonts/DejaVuSans-Bold.otf", 40 | "fonts/hold/UbuntuMono-Bold.otf", 41 | "fonts/hold/UbuntuMono-BoldItalic.otf", 42 | "fonts/hold/UbuntuMono-Regular.otf", 43 | "fonts/hold/UbuntuMono-Italic.otf" 44 | ], 45 | "syntaxhighlighting": true, 46 | "show_comments": false 47 | }, 48 | "mobi": { 49 | "index": true, 50 | "toc": true, 51 | "embedded_fonts": [ 52 | "fonts/DejaVuSerif.otf", 53 | "fonts/DejaVuSans-Bold.otf", 54 | "fonts/hold/UbuntuMono-Bold.otf", 55 | "fonts/hold/UbuntuMono-BoldItalic.otf", 56 | "fonts/hold/UbuntuMono-Regular.otf", 57 | "fonts/hold/UbuntuMono-Italic.otf" 58 | ], 59 | "syntaxhighlighting": true, 60 | "show_comments": false 61 | }, 62 | "html": { 63 | "index": true, 64 | "toc": true, 65 | "syntaxhighlighting": true, 66 | "show_comments": false, 67 | "consolidate": false, 68 | "consolidated": false 69 | } 70 | }, 71 | "theme": "oreillymedia/atlas_tech1c_theme", 72 | "title": "Pro Git" 73 | } 74 | -------------------------------------------------------------------------------- /book/04-git-server/sections/smart-http.asc: -------------------------------------------------------------------------------- 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 发送的请求路径和头部信息, 7 | 来判断该客户端是否支持 HTTP 通信(不低于 1.6.6 版本的客户端支持此特性)。 8 | 如果 CGI 发现该客户端支持智能(Smart)模式,它将会以智能模式与它进行通信, 9 | 否则它将会回落到哑(Dumb)模式下(因此它可以对某些老的客户端实现向下兼容)。 10 | 11 | 在完成以上简单的安装步骤后, 12 | 我们将用 Apache 来作为 CGI 服务器。 13 | 如果你没有安装 Apache,你可以在 Linux 环境下执行如下或类似的命令来安装:(((Apache))) 14 | 15 | [source,console] 16 | ---- 17 | $ sudo apt-get install apache2 apache2-utils 18 | $ a2enmod cgi alias env 19 | ---- 20 | 21 | 该操作将会启用 `mod_cgi`, `mod_alias` 和 `mod_env` 等 Apache 模块, 这些模块都是使该功能正常工作所必须的。 22 | 23 | 你还需要将 `/srv/git` 的 Unix 用户组设置为 `www-data`,这样 Web 服务器才能读写该仓库, 24 | 因为运行 CGI 脚本的 Apache 实例默认会以该用户的权限运行: 25 | 26 | [source,console] 27 | ---- 28 | $ chgrp -R www-data /srv/git 29 | ---- 30 | 31 | 接下来我们要向 Apache 配置文件添加一些内容,来让 `git-http-backend` 作为 Web 服务器对 `/git` 路径请求的处理器。 32 | 33 | [source,console] 34 | ---- 35 | SetEnv GIT_PROJECT_ROOT /srv/git 36 | SetEnv GIT_HTTP_EXPORT_ALL 37 | ScriptAlias /git/ /usr/lib/git-core/git-http-backend/ 38 | ---- 39 | 40 | 如果留空 `GIT_HTTP_EXPORT_ALL` 这个环境变量,Git 将只对无授权客户端提供带 `git-daemon-export-ok` 文件的版本库,就像 Git 守护进程一样。 41 | 42 | 最后,如果想让 Apache 允许 `git-http-backend` 请求并实现写入操作的授权验证,使用如下授权屏蔽配置即可: 43 | 44 | [source,console] 45 | ---- 46 | 47 | AuthType Basic 48 | AuthName "Git Access" 49 | AuthUserFile /srv/git/.htpasswd 50 | Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#) 51 | Require valid-user 52 | 53 | ---- 54 | 55 | 这需要你创建一个包含所有合法用户密码的 `.htpasswd` 文件。 56 | 以下是一个添加 “schacon” 用户到此文件的例子: 57 | 58 | [source,console] 59 | ---- 60 | $ htpasswd -c /srv/git/.htpasswd schacon 61 | ---- 62 | 63 | 你可以通过许多方式添加 Apache 授权用户,选择使用其中一种方式即可。 64 | 以上仅仅只是我们可以找到的最简单的一个例子。 65 | 如果愿意的话,你也可以通过 SSL 运行它,以保证所有数据是在加密状态下进行传输的。 66 | 67 | 我们不想深入去讲解 Apache 配置文件,因为你可能会使用不同的 Web 服务器,或者可能有不同的授权需求。 68 | 它的主要原理是使用一个 Git 附带的,名为 `git-http-backend` 的 CGI。它被引用来处理协商通过 HTTP 发送和接收的数据。 69 | 它本身并不包含任何授权功能,但是授权功能可以在 Web 服务器层引用它时被轻松实现。 70 | 你可以在任何所有可以处理 CGI 的 Web 服务器上办到这点,所以随便挑一个你最熟悉的 Web 服务器试手吧。 71 | 72 | [NOTE] 73 | ==== 74 | 欲了解更多的有关配置 Apache 授权访问的信息,请通过以下链接浏览 Apache 文档: 75 | https://httpd.apache.org/docs/current/howto/auth.html[] 76 | ==== 77 | -------------------------------------------------------------------------------- /book/B-embedding-git/sections/go-git.asc: -------------------------------------------------------------------------------- 1 | === go-git 2 | 3 | (((go-git)))(((Go))) 4 | 如果你想将 Git 集成到用 Golang 编写的服务中,这里还有一个纯 Go 库的实现。 5 | 这个库的实现没有任何原生依赖,因此不易出现手动管理内存的错误。 6 | 它对于标准 Golang 性能分析工具(如 CPU、内存分析器、竞争检测器等)也是透明的。 7 | 8 | go-git 专注于可扩展性、兼容性并支持大多数管道 API,记录在 https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md[]. 9 | 10 | 以下是使用 Go API 的基本示例: 11 | 12 | [source, go] 13 | ----- 14 | import "gopkg.in/src-d/go-git.v4" 15 | 16 | r, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{ 17 | URL: "https://github.com/src-d/go-git", 18 | Progress: os.Stdout, 19 | }) 20 | ----- 21 | 22 | 你只要拥有一个 `Repository` 实例,就可以访问相应仓库信息并对其进行改变: 23 | 24 | 25 | [source, go] 26 | ----- 27 | // 获取 HEAD 指向的分支 28 | ref, err := r.Head() 29 | 30 | // 获取由 ref 指向的提交对象 31 | commit, err := r.CommitObject(ref.Hash()) 32 | 33 | // 检索提交历史 34 | history, err := commit.History() 35 | 36 | // 遍历并逐个打印提交 37 | for _, c := range history { 38 | fmt.Println(c) 39 | } 40 | ----- 41 | 42 | 43 | ==== 高级功能 44 | 45 | go-git 几乎没有值得注意的高级功能,其中之一是可插拔存储系统,类似于 Libgit2 后端。 46 | 默认实现是内存存储,速度非常快。 47 | 48 | [source, go] 49 | ----- 50 | r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{ 51 | URL: "https://github.com/src-d/go-git", 52 | }) 53 | ----- 54 | 55 | 可插拔存储提供了许多有趣的选项。 56 | 例如,https://github.com/go-git/go-git/tree/master/_examples/storage[] 允许你在 Aerospike 数据库中存储引用、对象和配置。 57 | 58 | 另一个特性是灵活的文件系统抽象。 59 | 使用 https://godoc.org/github.com/src-d/go-billy#Filesystem[] 可以很容易以不同的方式存储所有文件,即通过将所有文件打包到磁盘上的单个归档文件或保存它们都在内存中。 60 | 61 | 另一个高级用例包括一个可微调的 HTTP 客户端,例如 https://github.com/go-git/go-git/blob/master/_examples/custom_http/main.go[] 中的案例。 62 | 63 | [source, go] 64 | ----- 65 | customClient := &http.Client{ 66 | Transport: &http.Transport{ // 接受任何证书(可能对测试有用) 67 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 68 | }, 69 | Timeout: 15 * time.Second, // 15 秒超时 70 | CheckRedirect: func(req *http.Request, via []*http.Request) error { 71 | return http.ErrUseLastResponse // 不要跟随重定向 72 | }, 73 | } 74 | 75 | // 覆盖 http(s) 默认协议以使用我们的自定义客户端 76 | client.InstallProtocol("https", githttp.NewClient(customClient)) 77 | 78 | // 如果协议为 https://,则使用新客户端克隆存储库 79 | r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{URL: url}) 80 | ----- 81 | 82 | 83 | ==== 延伸阅读 84 | 85 | 对 go-git 功能的全面介绍超出了本书的范围。 86 | 如果您想了解有关 go-git 的更多信息,请参阅 https://godoc.org/gopkg.in/src-d/go-git.v4[] 上的 API 文档, 以及 https://github.com/go-git/go-git/tree/master/_examples[] 上的系列使用示例。 -------------------------------------------------------------------------------- /book/02-git-basics/sections/getting-a-repository.asc: -------------------------------------------------------------------------------- 1 | [[_getting_a_repo]] 2 | === 获取 Git 仓库 3 | 4 | 通常有两种获取 Git 项目仓库的方式: 5 | 6 | 1. 将尚未进行版本控制的本地目录转换为 Git 仓库; 7 | 2. 从其它服务器 *克隆* 一个已存在的 Git 仓库。 8 | 9 | 两种方式都会在你的本地机器上得到一个工作就绪的 Git 仓库。 10 | 11 | ==== 在已存在目录中初始化仓库 12 | 13 | 如果你有一个尚未进行版本控制的项目目录,想要用 Git 来控制它,那么首先需要进入该项目目录中。 14 | 如果你还没这样做过,那么不同系统上的做法有些不同: 15 | 16 | 在 Linux 上: 17 | [source,console] 18 | ---- 19 | $ cd /home/user/my_project 20 | ---- 21 | 在 macOS 上: 22 | [source,console] 23 | ---- 24 | $ cd /Users/user/my_project 25 | ---- 26 | 在 Windows 上: 27 | [source,console] 28 | ---- 29 | $ cd /c/user/my_project 30 | ---- 31 | 32 | 之后执行: 33 | 34 | [source,console] 35 | ---- 36 | $ git init 37 | ---- 38 | 39 | 该命令将创建一个名为 `.git` 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 40 | 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。 41 | (参见 <> 来了解更多关于到底 `.git` 文件夹中包含了哪些文件的信息。)(((git commands, init))) 42 | 43 | 如果在一个已存在文件的文件夹(而非空文件夹)中进行版本控制,你应该开始追踪这些文件并进行初始提交。 44 | 可以通过 `git add` 命令来指定所需的文件来进行追踪,然后执行 `git commit` : 45 | 46 | [source,console] 47 | ---- 48 | $ git add *.c 49 | $ git add LICENSE 50 | $ git commit -m 'initial project version' 51 | ---- 52 | 53 | 稍后我们再逐一解释这些指令的行为。 54 | 现在,你已经得到了一个存在被追踪文件与初始提交的 Git 仓库。 55 | 56 | [[_git_cloning]] 57 | ==== 克隆现有的仓库 58 | 59 | 如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 `git clone` 命令。 60 | 如果你对其它的 VCS 系统(比如说 Subversion)很熟悉,请留心一下你所使用的命令是"clone"而不是"checkout"。 61 | 这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。 62 | 当你执行 `git clone` 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。 63 | 事实上,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库 64 | (虽然可能会丢失某些服务器端的钩子(hook)设置,但是所有版本的数据仍在,详见 <> )。 65 | 66 | 克隆仓库的命令是 `git clone ` 。(((git commands, clone))) 67 | 比如,要克隆 Git 的链接库 `libgit2`,可以用下面的命令: 68 | 69 | [source,console] 70 | ---- 71 | $ git clone https://github.com/libgit2/libgit2 72 | ---- 73 | 74 | 这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 `.git` 文件夹, 75 | 从远程仓库拉取下所有数据放入 `.git` 文件夹,然后从中读取最新版本的文件的拷贝。 76 | 如果你进入到这个新建的 `libgit2` 文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。 77 | 78 | 如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名: 79 | 80 | [source,console] 81 | ---- 82 | $ git clone https://github.com/libgit2/libgit2 mylibgit 83 | ---- 84 | 85 | 这会执行与上一条命令相同的操作,但目标目录名变为了 `mylibgit`。 86 | 87 | Git 支持多种数据传输协议。 88 | 上面的例子使用的是 `https://` 协议,不过你也可以使用 `git://` 协议或者使用 SSH 传输协议,比如 `user@server:path/to/repo.git` 。 89 | <> 将会介绍所有这些协议在服务器端如何配置使用,以及各种方式之间的利弊。 90 | -------------------------------------------------------------------------------- /book/03-git-branching/sections/workflows.asc: -------------------------------------------------------------------------------- 1 | === 分支开发工作流 2 | 3 | 现在你已经学会新建和合并分支,那么你可以或者应该用它来做些什么呢? 4 | 在本节,我们会介绍一些常见的利用分支进行开发的工作流程。而正是由于分支管理的便捷, 5 | 才衍生出这些典型的工作模式,你可以根据项目实际情况选择一种用用看。 6 | 7 | ==== 长期分支 8 | 9 | (((branches, long-running))) 10 | 因为 Git 使用简单的三方合并,所以就算在一段较长的时间内,反复把一个分支合并入另一个分支,也不是什么难事。 11 | 也就是说,在整个项目开发周期的不同阶段,你可以同时拥有多个开放的分支;你可以定期地把某些主题分支合并入其他分支中。 12 | 13 | 许多使用 Git 的开发者都喜欢使用这种方式来工作,比如只在 `master` 分支上保留完全稳定的代码——有可能仅仅是已经发布或即将发布的代码。 14 | 他们还有一些名为 `develop` 或者 `next` 的平行分支,被用来做后续开发或者测试稳定性——这些分支不必保持绝对稳定,但是一旦达到稳定状态,它们就可以被合并入 `master` 分支了。 15 | 这样,在确保这些已完成的主题分支(短期分支,比如之前的 `iss53` 分支)能够通过所有测试,并且不会引入更多 bug 之后,就可以合并入主干分支中,等待下一次的发布。 16 | 17 | 事实上我们刚才讨论的,是随着你的提交而不断右移的指针。 18 | 稳定分支的指针总是在提交历史中落后一大截,而前沿分支的指针往往比较靠前。 19 | 20 | .趋于稳定分支的线性图 21 | image::images/lr-branches-1.png[趋于稳定分支的线性图。] 22 | 23 | 通常把他们想象成流水线(work silos)可能更好理解一点,那些经过测试考验的提交会被遴选到更加稳定的流水线上去。 24 | 25 | [[lrbranch_b]] 26 | .趋于稳定分支的流水线(“silo”)视图 27 | image::images/lr-branches-2.png[趋于稳定分支的工作流(“silo”)视图。] 28 | 29 | 你可以用这种方法维护不同层次的稳定性。 30 | 一些大型项目还有一个 `proposed`(建议) 或 `pu: proposed updates`(建议更新)分支,它可能因包含一些不成熟的内容而不能进入 `next` 或者 `master` 分支。 31 | 这么做的目的是使你的分支具有不同级别的稳定性;当它们具有一定程度的稳定性后,再把它们合并入具有更高级别稳定性的分支中。 32 | 再次强调一下,使用多个长期分支的方法并非必要,但是这么做通常很有帮助,尤其是当你在一个非常庞大或者复杂的项目中工作时。 33 | 34 | [[_topic_branch]] 35 | ==== 主题分支 36 | 37 | (((branches, topic))) 38 | 主题分支对任何规模的项目都适用。 39 | 主题分支是一种短期分支,它被用来实现单一特性或其相关工作。 40 | 也许你从来没有在其他的版本控制系统(`VCS`)上这么做过,因为在那些版本控制系统中创建和合并分支通常很费劲。 41 | 然而,在 Git 中一天之内多次创建、使用、合并、删除分支都很常见。 42 | 43 | 你已经在上一节中你创建的 `iss53` 和 `hotfix` 主题分支中看到过这种用法。 44 | 你在上一节用到的主题分支(`iss53` 和 `hotfix` 分支)中提交了一些更新,并且在它们合并入主干分支之后,你又删除了它们。 45 | 这项技术能使你快速并且完整地进行上下文切换(context-switch)——因为你的工作被分散到不同的流水线中,在不同的流水线中每个分支都仅与其目标特性相关,因此,在做代码审查之类的工作的时候就能更加容易地看出你做了哪些改动。 46 | 你可以把做出的改动在主题分支中保留几分钟、几天甚至几个月,等它们成熟之后再合并,而不用在乎它们建立的顺序或工作进度。 47 | 48 | 考虑这样一个例子,你在 `master` 分支上工作到 `C1`,这时为了解决一个问题而新建 `iss91` 分支,在 `iss91` 分支上工作到 `C4`,然而对于那个问题你又有了新的想法,于是你再新建一个 `iss91v2` 分支试图用另一种方法解决那个问题,接着你回到 `master` 分支工作了一会儿,你又冒出了一个不太确定的想法,你便在 `C10` 的时候新建一个 `dumbidea` 分支,并在上面做些实验。 49 | 你的提交历史看起来像下面这个样子: 50 | 51 | .拥有多个主题分支的提交历史 52 | image::images/topic-branches-1.png[拥有多个主题分支的提交历史。] 53 | 54 | 现在,我们假设两件事情:你决定使用第二个方案来解决那个问题,即使用在 `iss91v2` 分支中方案。 55 | 另外,你将 `dumbidea` 分支拿给你的同事看过之后,结果发现这是个惊人之举。 56 | 这时你可以抛弃 `iss91` 分支(即丢弃 `C5` 和 `C6` 提交),然后把另外两个分支合并入主干分支。 57 | 最终你的提交历史看起来像下面这个样子: 58 | 59 | .合并了 `dumbidea` 和 `iss91v2` 分支之后的提交历史 60 | image::images/topic-branches-2.png[合并了 `dumbidea` 和 `iss91v2` 分支之后的提交历史。] 61 | 62 | 我们将会在 <> 中向你揭示更多有关分支工作流的细节, 63 | 因此,请确保你阅读完那个章节之后,再来决定你的下个项目要使用什么样的分支策略(branching scheme)。 64 | 65 | 请牢记,当你做这么多操作的时候,这些分支全部都存于本地。 66 | 当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中 —— 没有与服务器发生交互。 67 | -------------------------------------------------------------------------------- /images/basic-branching-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/basic-branching-1 9 | 10 | 11 | 12 | 13 | images/basic-branching-1 14 | Created with Sketch. 15 | 16 | 17 | C0 18 | 19 | 20 | 21 | 22 | 23 | C1 24 | 25 | 26 | 27 | C2 28 | 29 | 30 | 31 | 32 | 33 | master 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /book/06-github/sections/1-setting-up-account.asc: -------------------------------------------------------------------------------- 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 | 18 | GitHub 的付费计划包含一些高级工具和功能,不过本书将不涉及这部分内容。 19 | 关于可选方案及其对比的更多信息见 https://github.com/pricing[]。 20 | ==== 21 | 22 | 点击屏幕左上角的章鱼猫(Octocat)图标,你将来到控制面板页面。 23 | 现在,你已经做好了使用 GitHub 的准备工作。 24 | 25 | ==== SSH 访问 26 | 27 | (((SSH keys, with GitHub))) 28 | 现在,你完全可以使用 `https://` 协议,通过你刚刚创建的用户名和密码访问 Git 版本库。 29 | 但是,如果仅仅克隆公有项目,你甚至不需要注册——刚刚我们创建的账户是为了以后 fork 其它项目,以及推送我们自己的修改。 30 | 31 | 如果你习惯使用 SSH 远程,你需要配置一个公钥。 32 | (如果你没有公钥,参考 <>。) 33 | 使用窗口右上角的链接打开你的账户设置: 34 | 35 | .“Account settings”链接。 36 | image::images/account-settings.png[“Account settings”链接。] 37 | 38 | 然后在左侧选择“SSH keys”部分。 39 | 40 | .“SSH keys”链接。 41 | image::images/ssh-keys.png[“SSH keys”链接。] 42 | 43 | 在这个页面点击“`Add an SSH key`”按钮,给你的公钥起一个名字,将你的 `~/.ssh/id_rsa.pub` 44 | (或者自定义的其它名字)公钥文件的内容粘贴到文本区,然后点击“Add key”。 45 | 46 | [NOTE] 47 | ==== 48 | 确保给你的 SSH 密钥起一个能够记得住的名字。 49 | 你可以为每一个密钥起名字(例如,“我的笔记本电脑”或者“工作账户”等),以便以后需要吊销密钥时能够方便地区分。 50 | ==== 51 | 52 | [[_personal_avatar]] 53 | ==== 头像 54 | 55 | 下一步,如果愿意的话,你可以将生成的头像换成你喜欢的图片。 56 | 首先,来到“Profile”标签页(在“SSH Keys”标签页上方),点击“Upload new picture”。 57 | 58 | .“Profile”链接。 59 | image::images/your-profile.png[“Profile”链接。] 60 | 61 | 我们选择了本地磁盘上的一个 Git 图标,上传之后还可以对其进行裁剪。 62 | 63 | .裁剪头像 64 | image::images/avatar-crop.png[裁剪已上传的头像。] 65 | 66 | 现在,在网站任意有你参与的位置,人们都可以在你的用户名旁边看到你的头像。 67 | 68 | 如果你已经把头像上传到了流行的 Gravatar 托管服务(Wordpress 账户经常使用),默认就会使用这个头像,因此,你就不需要进行这一步骤了。 69 | 70 | ==== 邮件地址 71 | 72 | GitHub 使用用户邮件地址区分 Git 提交。 73 | 如果你在自己的提交中使用了多个邮件地址,希望 GitHub 可以正确地将它们连接起来, 74 | 你需要在管理页面的 Emails 部分添加你拥有的所有邮箱地址。 75 | 76 | [[_add_email_addresses]] 77 | .添加邮件地址 78 | image::images/email-settings.png[添加所有邮件地址。] 79 | 80 | 在 <<_add_email_addresses>> 中我们可以看到一些不同的状态。 81 | 顶部的地址是通过验证的,并且被设置为主要地址,这意味着该地址会接收到所有的通知和回复。 82 | 第二个地址是通过验证的,如果愿意的话,可以将其设置为主要地址。 83 | 最后一个地址是未通过验证的,这意味着你不能将其设置为主要地址。 84 | 当 GitHub 发现任意版本库中的任意提交信息包含了这些地址,它就会将其链接到你的账户。 85 | 86 | ==== 两步验证 87 | 88 | 最后,为了额外的安全性,你绝对应当设置两步验证,简写为 “2FA”。 89 | 两步验证是一种用于降低因你的密码被盗而带来的账户风险的验证机制,现在已经变得越来越流行。 90 | 开启两步验证,GitHub 会要求你用两种不同的验证方法,这样,即使其中一个被攻破,攻击者也不能访问你的账户。 91 | 92 | 你可以在 Account settings 页面的 Security 标签页中找到 Two-factor Authentication 设置。 93 | 94 | .Security 标签页中的 2FA 95 | image::images/2fa-1.png[Security 标签页中的 2FA] 96 | 97 | 点击“Set up two-factor authentication”按钮,会跳转到设置页面。该页面允许你选择是要在登录时使用手机 app 生成辅助码(一种“基于时间的一次性密码”),还是要 GitHub 通过 SMS 发送辅助码。 98 | 99 | 选择合适的方法后,按照提示步骤设置 2FA,你的账户会变得更安全,每次登录 GitHub 时都需要提供除密码以外的辅助码。 100 | -------------------------------------------------------------------------------- /book/05-distributed-git/sections/distributed-workflows.asc: -------------------------------------------------------------------------------- 1 | === 分布式工作流程 2 | 3 | (((workflows))) 4 | 与传统的集中式版本控制系统(CVCS)相反,Git 的分布式特性使得开发者间的协作变得更加灵活多样。 5 | 在集中式系统中,每个开发者就像是连接在集线器上的节点,彼此的工作方式大体相像。 6 | 而在 Git 中,每个开发者同时扮演着节点和集线器的角色——也就是说, 7 | 每个开发者既可以将自己的代码贡献到其他的仓库中,同时也能维护自己的公开仓库, 8 | 让其他人可以在其基础上工作并贡献代码。 9 | 由此,Git 的分布式协作可以为你的项目和团队衍生出种种不同的工作流程, 10 | 接下来的章节会介绍几种利用了 Git 的这种灵活性的常见应用方式。 11 | 我们将讨论每种方式的优点以及可能的缺点;你可以选择使用其中的某一种,或者将它们的特性混合搭配使用。 12 | 13 | ==== 集中式工作流 14 | 15 | (((workflows, centralized))) 16 | 集中式系统中通常使用的是单点协作模型——集中式工作流。 17 | 一个中心集线器,或者说 *仓库*,可以接受代码,所有人将自己的工作与之同步。 18 | 若干个开发者则作为节点,即中心仓库的消费者与中心仓库同步。 19 | 20 | .集中式工作流。 21 | image::images/centralized_workflow.png[集中式工作流。] 22 | 23 | 这意味着如果两个开发者从中心仓库克隆代码下来,同时作了一些修改,那么只有第一个开发者可以顺利地把数据推送回共享服务器。 24 | 第二个开发者在推送修改之前,必须先将第一个人的工作合并进来,这样才不会覆盖第一个人的修改。 25 | 这和 Subversion(((Subversion))) (或任何 CVCS)中的概念一样,而且这个模式也可以很好地运用到 Git 中。 26 | 27 | 如果在公司或者团队中,你已经习惯了使用这种集中式工作流程,完全可以继续采用这种简单的模式。 28 | 只需要搭建好一个中心仓库,并给开发团队中的每个人推送数据的权限,就可以开展工作了。Git 不会让用户覆盖彼此的修改。 29 | 30 | 例如 John 和 Jessica 同时开始工作。 31 | John 完成了他的修改并推送到服务器。 32 | 接着 Jessica 尝试提交她自己的修改,却遭到服务器拒绝。 33 | 她被告知她的修改正通过非快进式(non-fast-forward)的方式推送,只有将数据抓取下来并且合并后方能推送。 34 | 这种模式的工作流程的使用非常广泛,因为大多数人对其很熟悉也很习惯。 35 | 36 | 当然这并不局限于小团队。 37 | 利用 Git 的分支模型,通过同时在多个分支上工作的方式,即使是上百人的开发团队也可以很好地在单个项目上协作。 38 | 39 | [[_integration_manager]] 40 | ==== 集成管理者工作流 41 | 42 | (((workflows, integration manager))) 43 | Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。 44 | 这种情形下通常会有个代表“官方”项目的权威的仓库。 45 | 要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。 46 | 接着你可以请求官方仓库的维护者拉取更新合并到主项目。 47 | 维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。 48 | 这一流程的工作方式如下所示(见 <>): 49 | 50 | 1. 项目维护者推送到主仓库。 51 | 2. 贡献者克隆此仓库,做出修改。 52 | 3. 贡献者将数据推送到自己的公开仓库。 53 | 4. 贡献者给维护者发送邮件,请求拉取自己的更新。 54 | 5. 维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改。 55 | 6. 维护者将合并后的修改推送到主仓库。 56 | 57 | [[wfdiag_b]] 58 | .集成管理者工作流。 59 | image::images/integration-manager.png[集成管理者工作流。] 60 | 61 | (((forking))) 62 | 这是 GitHub 和 GitLab 等集线器式(hub-based)工具最常用的工作流程。人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。 63 | 这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。 64 | 贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己的节奏工作。 65 | 66 | ==== 主管与副主管工作流 67 | 68 | (((workflows, dictator and lieutenants))) 69 | 这其实是多仓库工作流程的变种。 70 | 一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 71 | 被称为 *副主管(lieutenant)* 的各个集成管理者分别负责集成项目中的特定部分。 72 | 所有这些副主管头上还有一位称为 *主管(dictator)* 的总集成管理者负责统筹。 73 | 主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。 74 | 整个流程看起来是这样的(见 <> ): 75 | 76 | 1. 普通开发者在自己的主题分支上工作,并根据 `master` 分支进行变基。 77 | 这里是主管推送的参考仓库的 `master` 分支。 78 | 2. 副主管将普通开发者的主题分支合并到自己的 `master` 分支中。 79 | 3. 主管将所有副主管的 `master` 分支并入自己的 `master` 分支中。 80 | 4. 最后,主管将集成后的 `master` 分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基。 81 | 82 | [[wfdiag_c]] 83 | .主管与副主管工作流。 84 | image::images/benevolent-dictator.png[主管与副主管工作流。] 85 | 86 | 这种工作流程并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。 87 | 利用这种方式,项目总负责人(即主管)可以把大量分散的集成工作委托给不同的小组负责人分别处理,然后在不同时刻将大块的代码子集统筹起来,用于之后的整合。 88 | 89 | ==== 工作流程总结 90 | 91 | 上面介绍了在 Git 等分布式系统中经常使用的工作流程,但是在实际的开发中,你会遇到许多可能适合你的特定工作流程的变种。 92 | 现在你应该已经清楚哪种工作流程组合可能比较适合你了,我们会给出一些如何扮演不同工作流程中主要角色的更具体的例子。 93 | 下一节我们将会学习为项目做贡献的一些常用模式。 94 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | **Which version of the book is affected?** 22 | 23 | 24 | 25 | **Describe the bug:** 26 | 27 | 28 | **Steps to reproduce:** 29 | 30 | 31 | 32 | 33 | 34 | 35 | **Expected behavior:** 36 | 37 | 38 | **Screenshots:** 39 | 40 | 41 | **Additional context:** 42 | 43 | 44 | 45 | **Desktop:** 46 | 47 | 48 | - Operating system: 49 | - Browser/application: 50 | - Browser/application version: 51 | 52 | **Smartphone:** 53 | 54 | 55 | - Device: 56 | - OS: 57 | - Browser/application: 58 | - Browser/application version: 59 | 60 | **E-book reader:** 61 | 62 | 63 | - Device: 64 | - Software Update: 65 | -------------------------------------------------------------------------------- /book/04-git-server/sections/git-on-a-server.asc: -------------------------------------------------------------------------------- 1 | [[_getting_git_on_a_server]] 2 | === 在服务器上搭建 Git 3 | 4 | 现在我们将讨论如何在你自己的服务器上搭建 Git 服务来运行这些协议。 5 | 6 | [NOTE] 7 | ==== 8 | 这里我们将要演示在 Linux 服务器上进行一次基本且简化的安装所需的命令与步骤,当然在 macOS 或 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 连接, 41 | 你想把所有的 Git 仓库放在 `/srv/git` 目录下。 42 | 假设服务器上存在 `/srv/git/` 目录,你可以通过以下命令复制你的裸仓库来创建一个新仓库: 43 | 44 | [source,console] 45 | ---- 46 | $ scp -r my_project.git user@git.example.com:/srv/git 47 | ---- 48 | 49 | 此时,其他可通过 SSH 读取此服务器上 `/srv/git` 目录的用户,可运行以下命令来克隆你的仓库。 50 | 51 | [source,console] 52 | ---- 53 | $ git clone user@git.example.com:/srv/git/my_project.git 54 | ---- 55 | 56 | 如果一个用户,通过使用 SSH 连接到一个服务器,并且其对 `/srv/git/my_project.git` 目录拥有可写权限,那么他将自动拥有推送权限。 57 | 58 | 如果到该项目目录中运行 `git init` 命令,并加上 `--shared` 选项, 59 | 那么 Git 会自动修改该仓库目录的组权限为可写。 60 | 注意,运行此命令的工程中不会摧毁任何提交、引用等内容。(((git commands, init, bare))) 61 | 62 | [source,console] 63 | ---- 64 | $ ssh user@git.example.com 65 | $ cd /srv/git/my_project.git 66 | $ git init --bare --shared 67 | ---- 68 | 69 | 由此可见,根据现有的 Git 仓库创建一个裸仓库,然后把它放上你和协作者都有 SSH 访问权的服务器是多么容易。 70 | 现在你们已经准备好在同一项目上展开合作了。 71 | 72 | 值得注意的是,这的确是架设一个几个人拥有连接权的 Git 服务的全部—— 73 | 只要在服务器上加入可以用 SSH 登录的帐号,然后把裸仓库放在大家都有读写权限的地方。 74 | 你已经准备好了一切,无需更多。 75 | 76 | 下面的几节中,你会了解如何扩展到更复杂的设定。 77 | 这些内容包含如何避免为每一个用户建立一个账户,给仓库添加公共读取权限,架设网页界面等等。 78 | 然而,请记住这一点,如果只是和几个人在一个私有项目上合作的话,__仅仅__ 是一个 SSH 服务器和裸仓库就足够了。 79 | 80 | ==== 小型安装 81 | 82 | 如果设备较少或者你只想在小型开发团队里尝试 Git ,那么一切都很简单。 83 | 架设 Git 服务最复杂的地方在于用户管理。 84 | 如果需要仓库对特定的用户可读,而给另一部分用户读写权限,那么访问和许可安排就会比较困难。 85 | 86 | ===== SSH 连接 87 | 88 | (((serving repositories, SSH))) 89 | 如果你有一台所有开发者都可以用 SSH 连接的服务器,架设你的第一个仓库就十分简单了, 90 | 因为你几乎什么都不用做(正如我们上一节所说的)。 91 | 如果你想在你的仓库上设置更复杂的访问控制权限,只要使用服务器操作系统的普通的文件系统权限就行了。 92 | 93 | 如果需要团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户,那么提供 SSH 连接就是唯一的选择了。 94 | 我们假设用来共享仓库的服务器已经安装了 SSH 服务,而且你通过它访问服务器。 95 | 96 | 有几个方法可以使你给团队每个成员提供访问权。 97 | 第一个就是给团队里的每个人创建账号,这种方法很直接但也很麻烦。 98 | 或许你不会想要为每个人运行一次 `adduser`(或者 `useradd`)并且设置临时密码。 99 | 100 | 第二个办法是在主机上建立一个 'git' 账户,让每个需要写权限的人发送一个 SSH 公钥, 101 | 然后将其加入 git 账户的 `~/.ssh/authorized_keys` 文件。 102 | 这样一来,所有人都将通过 'git' 账户访问主机。 103 | 这一点也不会影响提交的数据——访问主机用的身份不会影响提交对象的提交者信息。 104 | 105 | 另一个办法是让 SSH 服务器通过某个 LDAP 服务,或者其他已经设定好的集中授权机制,来进行授权。 106 | 只要每个用户可以获得主机的 shell 访问权限,任何 SSH 授权机制你都可视为是有效的。 107 | -------------------------------------------------------------------------------- /book/09-git-and-other-scms/sections/import-p4.asc: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /book/A-git-in-other-environments/sections/powershell.asc: -------------------------------------------------------------------------------- 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 | 这种方法同样适用于 Linux 或 macOS 上运行的 PowerShell Core。 8 | 一个名为 posh-git (https://github.com/dahlbyk/posh-git[]) 的扩展包提供了强大的 tab 补全功能,并针对提示符进行了增强,以帮助你聚焦于你的仓库状态。 9 | 它看起来像: 10 | 11 | .附带了 posh-git 扩展包的 Powershell。 12 | image::images/posh-git.png[附带了 posh-git 扩展包的 Powershell] 13 | 14 | ==== 安装 15 | 16 | ===== 前提需求(仅限 Windows) 17 | 18 | 在可以运行 PowerShell 脚本之前,你需要将本地的 `ExecutionPolicy` 设置为 `RemoteSigned`(可以说是允许除了 `Undefined` 和 `Restricted` 之外的任何内容)。 19 | 如果你选择了 `AllSigned` 而非 `RemoteSigned`,那么你的本地脚本还需要数字签名后才能执行。 20 | 如果设置为 `RemoteSigned`,那么只有 `ZoneIdentifier` 设置为 `Internet`,即从 Web 上下载的脚本才需要签名,其它则不需要。 21 | 如果你是管理员,想要为本机上的所有用户设置它,请使用 `-Scope LocalMachine`。 22 | 如果你是没有管理权限的普通用户,可使用 `-Scope CurrentUser` 来只为自己设置它。 23 | 24 | 有关 PowerShell Scopes 的更多详情: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes[] 25 | 26 | 有关 PowerShell ExecutionPolicy 的更多详情: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy[] 27 | 28 | 对于所有用户使用以下命令来设置 `ExecutionPolicy` 为 `RemoteSigned`: 29 | 30 | [source,powershell] 31 | ----- 32 | > Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force 33 | ----- 34 | 35 | ===== PowerShell Gallery 36 | 37 | 如果你有 PowerShell 5 以上或安装了 PackageManagement 的 PowerShell 4,那么可以用包管理器来安装 posh-git。 38 | 39 | 有关 PowerShell Gallery 的更多详情: https://docs.microsoft.com/en-us/powershell/scripting/gallery/overview[] 40 | 41 | [source,powershell] 42 | ----- 43 | > Install-Module posh-git -Scope CurrentUser -Force 44 | > Install-Module posh-git -Scope CurrentUser -AllowPrerelease -Force # 带有 PowerShell Core 支持的更新的 beta 版 45 | ----- 46 | 47 | 如果你想为所有的用户安装 posh-git,请使用 `-Scope AllUsers` 并在管理员权限启动的 PowerShell 控制台中执行。 48 | 如果第二条命令执行失败并出现类似 `Module 'PowerShellGet' was not installed by using Install-Module` 这样的错误,那么你需要先运行另一条命令: 49 | 50 | [source,powershell] 51 | ---- 52 | > Install-Module PowerShellGet -Force -SkipPublisherCheck 53 | ---- 54 | 55 | 之后你可以再试一遍。 56 | 出现这个错误的原因是 Windows PowerShell 搭载的模块是以不同的发布证书签名的。 57 | 58 | ===== 更新 PowerShell 提示符 59 | 60 | 要在你的提示符中包含 Git 信息,那么需要导入 posh-git 模块。 61 | 要让 PowerShell 在每次启动时都导入 posh-git,请执行 `Add-PoshGitToProfile` 命令,它会在你的 `$profile` 脚本中添加导入语句。 62 | 此脚本会在每次打开新的 PowerShell 终端时执行。 63 | 注意,存在多个 `$profile` 脚本。 64 | 例如,其中一个是控制台的,另一个则属于 ISE。 65 | 66 | [source,powershell] 67 | ----- 68 | > Import-Module posh-git 69 | > Add-PoshGitToProfile -AllHosts 70 | ----- 71 | 72 | ===== 从源码安装 73 | 74 | 只需从 https://github.com/dahlbyk/posh-git[] 下载一份 posh-git 的发行版并解压即可。 75 | 接着使用 `posh-git.psd1` 文件的完整路径导入此模块: 76 | 77 | [source,powershell] 78 | ----- 79 | > Import-Module \src\posh-git.psd1 80 | > Add-PoshGitToProfile -AllHosts 81 | ----- 82 | 83 | 它将会向你的 `profile.ps1` 文件添加适当的内容,posh-git 将会在下次打开 PowerShell 时启用。 84 | 85 | 命令提示符显示的 Git 状态信息的解释见: https://github.com/dahlbyk/posh-git/blob/master/README.md#git-status-summary-information[] 86 | 如何定制 Posh-Git 提示符的详情见: https://github.com/dahlbyk/posh-git/blob/master/README.md#customization-variables[]。 87 | -------------------------------------------------------------------------------- /images/basic-branching-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/basic-branching-2 9 | 10 | 11 | 12 | 13 | images/basic-branching-2 14 | Created with Sketch. 15 | 16 | 17 | 18 | C0 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | C1 27 | 28 | 29 | 30 | C2 31 | 32 | 33 | 34 | master 35 | 36 | 37 | 38 | iss53 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /images/local.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/local 9 | 10 | 11 | 12 | images/local 13 | Created with Sketch. 14 | 15 | 16 | 17 | Local Computer 18 | 19 | Version Database 20 | Checkout 21 | 22 | 23 | File 24 | 25 | 26 | 27 | Version 3 28 | 29 | 30 | 31 | Version 2 32 | 33 | 34 | 35 | Version 1 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /book/07-git-tools/sections/subtree-merges.asc: -------------------------------------------------------------------------------- 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 --no-tags 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 | 你可以在 <> 中查看更多 `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 | 75 | [source,console] 76 | ---- 77 | $ git checkout master 78 | $ git merge --squash -s recursive -Xsubtree=rack rack_branch 79 | Squash commit -- not updating HEAD 80 | Automatic merge went well; stopped before committing as requested 81 | ---- 82 | 83 | Rack 项目中所有的改动都被合并了,等待被提交到本地。 84 | 你也可以用相反的方法——在 `master` 分支上的 `rack` 子目录中做改动然后将它们合并入你的 85 | `rack_branch` 分支中,之后你可能将其提交给项目维护着或者将它们推送到上游。 86 | 87 | 这给我们提供了一种类似子模块工作流的工作方式,但是它并不需要用到子模块 88 | (有关子模块的内容我们会在 <> 中介绍)。 89 | 我们可以在自己的仓库中保持一些和其他项目相关的分支,偶尔使用子树合并将它们合并到我们的项目中。 90 | 某些时候这种方式很有用,例如当所有的代码都提交到一个地方的时候。 91 | 然而,它同时也有缺点,它更加复杂且更容易让人犯错,例如重复合并改动或者不小心将分支提交到一个无关的仓库上去。 92 | 93 | 另外一个有点奇怪的地方是,当你想查看 `rack` 子目录和 `rack_branch` 分支的差异—— 94 | 来确定你是否需要合并它们——你不能使用普通的 `diff` 命令。 95 | 取而代之的是,你必须使用 `git diff-tree` 来和你的目标分支做比较: 96 | 97 | [source,console] 98 | ---- 99 | $ git diff-tree -p rack_branch 100 | ---- 101 | 102 | 或者,将你的 `rack` 子目录和最近一次从服务器上抓取的 `master` 分支进行比较,你可以运行: 103 | 104 | [source,console] 105 | ---- 106 | $ git diff-tree -p rack_remote/master 107 | ---- 108 | -------------------------------------------------------------------------------- /images/two-branches.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/two-branches 9 | 10 | 11 | 12 | 13 | images/two-branches 14 | Created with Sketch. 15 | 16 | 17 | 18 | 19 | 20 | master 21 | 22 | 23 | 24 | 25 | 26 | 27 | testing 28 | 29 | 30 | 31 | 32 | 33 | 34 | f30ab 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 34ac2 44 | 45 | 46 | 47 | 48 | 98ca9 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /book/01-introduction/sections/what-is-git.asc: -------------------------------------------------------------------------------- 1 | === Git 是什么? 2 | 3 | 那么,简单地说,Git 究竟是怎样的一个系统呢? 4 | 请注意接下来的内容非常重要,若你理解了 Git 的思想和基本工作原理,用起来就会知其所以然,游刃有余。 5 | 在学习 Git 时,请尽量理清你对其它版本管理系统已有的认识,如 CVS、Subversion 或 Perforce, 6 | 这样能帮助你使用工具时避免发生混淆。尽管 Git 用起来与其它的版本控制系统非常相似, 7 | 但它在对信息的存储和认知方式上却有很大差异,理解这些差异将有助于避免使用中的困惑。(((Subversion)))(((Perforce))) 8 | 9 | ==== 直接记录快照,而非差异比较 10 | 11 | Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方式。 12 | 从概念上来说,其它大部分系统以文件变更列表的方式存储信息,这类系统(CVS、Subversion、Perforce 等等) 13 | 将它们存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异 14 | (它们通常称作 *基于差异(delta-based)* 的版本控制)。 15 | 16 | .存储每个文件与初始版本的差异. 17 | image::images/deltas.png[存储每个文件与初始版本的差异。] 18 | 19 | Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 20 | 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 21 | 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 22 | Git 对待数据更像是一个 *快照流*。 23 | 24 | .存储项目随时间改变的快照. 25 | image::images/snapshots.png[Git 存储项目随时间改变的快照。] 26 | 27 | 这是 Git 与几乎所有其它版本控制系统的重要区别。 28 | 因此 Git 重新考虑了以前每一代版本控制系统延续下来的诸多方面。 29 | Git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不只是一个简单的 VCS。 30 | 稍后我们在<>讨论 Git 分支管理时,将探究这种方式对待数据所能获得的益处。 31 | 32 | ==== 近乎所有操作都是本地执行 33 | 34 | 在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。 35 | 如果你习惯于所有操作都有网络延时开销的集中式版本控制系统,Git 在这方面会让你感到速度之神赐给了 Git 超凡的能量。 36 | 因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。 37 | 38 | 举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 39 | 你能立即看到项目历史。如果你想查看当前版本与一个月前的版本之间引入的修改, 40 | Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。 41 | 42 | 这也意味着你在离线或者没有 VPN 时,几乎可以进行任何操作。 43 | 如你在飞机或火车上想做些工作,就能愉快地提交(到你的 *本地* 副本,还记得吗?), 44 | 直到有网络连接时再上传。如你回家后 VPN 客户端不正常,那么也仍能工作。 45 | 使用其它系统的话,做到这些是不可能或很费力的。 46 | 比如,用 Perforce 的话,没有连接服务器时几乎不能做什么事;而用 Subversion 和 CVS 的话, 47 | 你能修改文件,但不能向数据库提交修改(因为你的本地数据库离线了)。 48 | 这样似乎问题不大,但是你可能会惊喜地发现它带来的巨大的不同。 49 | 50 | ==== Git 保证完整性 51 | 52 | Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。 53 | 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 54 | 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 55 | 若你在传送过程中丢失信息或损坏文件,Git 就能发现。 56 | 57 | Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。(((SHA-1))) 58 | 这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。 59 | SHA-1 哈希看起来是这样: 60 | 61 | [source] 62 | ---- 63 | 24b9da6552252987aa493b52f8696cd6d3b00373 64 | ---- 65 | 66 | Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 67 | 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。 68 | 69 | ==== Git 一般只添加数据 70 | 71 | 你执行的 Git 操作,几乎只往 Git 数据库中 *添加* 数据。 72 | 你很难使用 Git 从数据库中删除数据,也就是说 Git 几乎不会执行任何可能导致文件不可恢复的操作。 73 | 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容。但是一旦你提交快照到 Git 中, 74 | 就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。 75 | 76 | 这使得我们使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。 77 | 更深度探讨 Git 如何保存数据及恢复丢失数据的话题,请参考<>。 78 | 79 | ==== 三种状态 80 | 81 | 现在请注意,如果你希望后面的学习更顺利,请记住下面这些关于 Git 的概念。 82 | Git 有三种状态,你的文件可能处于其中之一: *已提交(committed)*、*已修改(modified)* 和 *已暂存(staged)*。 83 | 84 | * 已修改表示修改了文件,但还没保存到数据库中。 85 | * 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。 86 | * 已提交表示数据已经安全地保存在本地数据库中。 87 | 88 | 这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。 89 | 90 | .工作目录、暂存区域以及 Git 仓库. 91 | image::images/areas.png[工作区、暂存区以及 Git 目录。] 92 | 93 | 工作区是对项目的某个版本独立提取出来的内容。 94 | 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。 95 | 96 | 暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 97 | 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。 98 | 99 | Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 100 | 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。 101 | 102 | 基本的 Git 工作流程如下: 103 | 104 | 1. 在工作区中修改文件。 105 | 2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。 106 | 3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。 107 | 108 | 如果 Git 目录中保存着特定版本的文件,就属于 *已提交* 状态。 109 | 如果文件已修改并放入暂存区,就属于 *已暂存* 状态。 110 | 如果自上次检出后,作了修改但还没有放到暂存区域,就是 *已修改* 状态。 111 | 在 <> 一章,你会进一步了解这些状态的细节, 112 | 并学会如何根据文件状态实施后续操作,以及怎样跳过暂存直接提交。 113 | -------------------------------------------------------------------------------- /book/01-introduction/sections/first-time-setup.asc: -------------------------------------------------------------------------------- 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 | 如果在执行 `git config` 时带上 `--system` 选项,那么它就会读写该文件中的配置变量。 13 | (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。) 14 | 2. `~/.gitconfig` 或 `~/.config/git/config` 文件:只针对当前用户。 15 | 你可以传递 `--global` 选项让 Git 读写此文件,这会对你系统上 **所有** 的仓库生效。 16 | 3. 当前使用仓库的 Git 目录中的 `config` 文件(即 `.git/config`):针对该仓库。 17 | 你可以传递 `--local` 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。 18 | (当然,你需要进入某个 Git 仓库中才能让该选项生效。) 19 | 20 | 每一个级别会覆盖上一级别的配置,所以 `.git/config` 的配置变量会覆盖 `/etc/gitconfig` 中的配置变量。 21 | 22 | 在 Windows 系统中,Git 会查找 `$HOME` 目录下(一般情况下是 `C:\Users\$USER` )的 `.gitconfig` 文件。 23 | Git 同样也会寻找 `/etc/gitconfig` 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。 24 | 如果你在 Windows 上使用 Git 2.x 以后的版本,那么还有一个系统级的配置文件,Windows XP 上在 25 | `C:\Documents and Settings\All Users\Application Data\Git\config` ,Windows Vista 及其以后的版本在 26 | `C:\ProgramData\Git\config` 。此文件只能以管理员权限通过 `git config -f ` 来修改。 27 | 28 | 你可以通过以下命令查看所有的配置以及它们所在的文件: 29 | 30 | [source,console] 31 | ---- 32 | $ git config --list --show-origin 33 | ---- 34 | 35 | ==== 用户信息 36 | 37 | 安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 38 | 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改: 39 | 40 | [source,console] 41 | ---- 42 | $ git config --global user.name "John Doe" 43 | $ git config --global user.email johndoe@example.com 44 | ---- 45 | 46 | 再次强调,如果使用了 `--global` 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 47 | 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 `--global` 选项的命令来配置。 48 | 49 | 很多 GUI 工具都会在第一次运行时帮助你配置这些信息。 50 | 51 | [[_editor]] 52 | ==== 文本编辑器 53 | 54 | 既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 55 | 如果未配置,Git 会使用操作系统默认的文本编辑器。 56 | 57 | 如果你想使用不同的文本编辑器,例如 Emacs,可以这样做: 58 | 59 | [source,console] 60 | ---- 61 | $ git config --global core.editor emacs 62 | ---- 63 | 64 | 在 Windows 系统上,如果你想要使用别的文本编辑器,那么必须指定可执行文件的完整路径。 65 | 它可能随你的编辑器的打包方式而不同。 66 | 67 | 对于 Notepad++,一个流行的代码编辑器来说,你可能想要使用 32 位的版本, 68 | 因为在本书编写时 64 位的版本尚不支持所有的插件。 69 | 如果你在使用 32 位的 Windows 系统,或在 64 位系统上使用 64 位的编辑器,那么你需要输入如下命令: 70 | 71 | [source,console] 72 | ---- 73 | $ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" 74 | ---- 75 | 76 | [NOTE] 77 | ==== 78 | Vim、Emacs 和 Notepad++ 都是流行的文本编辑器,通常程序员们会在 Linux 和 macOS 79 | 这类基于 Unix 的系统或 Windows 系统上使用它们。 80 | 如果你在使用其他的或 32 位版本的编辑器,请在 <> 81 | 中查看设置为该编辑器的具体步骤。 82 | ==== 83 | 84 | [WARNING] 85 | ==== 86 | 如果你不这样设置编辑器,那么当 Git 试图启动它时你可能会被弄糊涂、不知所措。 87 | 例如,在 Windows 上 Git 在开始编辑时可能会过早地结束。 88 | ==== 89 | 90 | ==== 检查配置信息 91 | 92 | 如果想要检查你的配置,可以使用 `git config --list` 命令来列出所有 Git 当时能找到的配置: 93 | 94 | [source,console] 95 | ---- 96 | $ git config --list 97 | user.name=John Doe 98 | user.email=johndoe@example.com 99 | color.status=auto 100 | color.branch=auto 101 | color.interactive=auto 102 | color.diff=auto 103 | ... 104 | ---- 105 | 106 | 你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:`/etc/gitconfig` 与 `~/.gitconfig`)。 107 | 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。 108 | 109 | 你可以通过输入 `git config `:(((git commands, config))) 来检查 Git 的某一项配置: 110 | 111 | [source,console] 112 | ---- 113 | $ git config user.name 114 | John Doe 115 | ---- 116 | 117 | [NOTE] 118 | ==== 119 | 由于 Git 会从多个文件中读取同一配置变量的不同值,因此你可能会在其中看到意料之外的值而不知道为什么。 120 | 此时,你可以查询 Git 中该变量的 **原始** 值,它会告诉你哪一个配置文件最后设置了该值: 121 | 122 | [source,console] 123 | ---- 124 | $ git config --show-origin rerere.autoUpdate 125 | file:/home/johndoe/.gitconfig false 126 | ---- 127 | ==== 128 | -------------------------------------------------------------------------------- /book/02-git-basics/sections/undoing.asc: -------------------------------------------------------------------------------- 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 | 26 | [source,console] 27 | ---- 28 | $ git commit -m 'initial commit' 29 | $ git add forgotten_file 30 | $ git commit --amend 31 | ---- 32 | 33 | 最终你只会有一个提交——第二次提交将代替第一次提交的结果。 34 | 35 | [NOTE] 36 | ==== 37 | 当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 *新的提交* 替换旧的提交, 38 | 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。 39 | 40 | 修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 41 | “小修补,修正笔误”这种提交信息弄乱你的仓库历史。 42 | ==== 43 | 44 | [[_unstaging]] 45 | ==== 取消暂存的文件 46 | 47 | 接下来的两个小节演示如何操作暂存区和工作目录中已修改的文件。 48 | 这些命令在修改文件状态的同时,也会提示如何撤消操作。 49 | 例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 50 | 但是却意外地输入 `git add *` 暂存了它们两个。如何只取消暂存两个中的一个呢? 51 | `git status` 命令提示了你: 52 | 53 | [source,console] 54 | ---- 55 | $ git add * 56 | $ git status 57 | On branch master 58 | Changes to be committed: 59 | (use "git reset HEAD ..." to unstage) 60 | 61 | renamed: README.md -> README 62 | modified: CONTRIBUTING.md 63 | ---- 64 | 65 | 在 “Changes to be committed” 文字正下方,提示使用 `git reset HEAD ...` 来取消暂存。 66 | 所以,我们可以这样来取消暂存 `CONTRIBUTING.md` 文件: 67 | 68 | [source,console] 69 | ---- 70 | $ git reset HEAD CONTRIBUTING.md 71 | Unstaged changes after reset: 72 | M CONTRIBUTING.md 73 | $ git status 74 | On branch master 75 | Changes to be committed: 76 | (use "git reset HEAD ..." to unstage) 77 | 78 | renamed: README.md -> README 79 | 80 | Changes not staged for commit: 81 | (use "git add ..." to update what will be committed) 82 | (use "git checkout -- ..." to discard changes in working directory) 83 | 84 | modified: CONTRIBUTING.md 85 | ---- 86 | 87 | 这个命令有点儿奇怪,但是起作用了。 88 | `CONTRIBUTING.md` 文件已经是修改未暂存的状态了。 89 | 90 | [NOTE] 91 | ===== 92 | `git reset` 确实是个危险的命令,如果加上了 `--hard` 选项则更是如此。 93 | 然而在上述场景中,工作目录中的文件尚未修改,因此相对安全一些。 94 | ===== 95 | 96 | 到目前为止这个神奇的调用就是你需要对 `git reset` 命令了解的全部。 97 | 我们将会在 <> 中了解 `reset` 的更多细节以及如何掌握它做一些真正有趣的事。 98 | 99 | ==== 撤消对文件的修改 100 | 101 | 如果你并不想保留对 `CONTRIBUTING.md` 文件的修改怎么办? 102 | 你该如何方便地撤消修改——将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)? 103 | 幸运的是,`git status` 也告诉了你应该如何做。 104 | 在最后一个例子中,未暂存区域是这样: 105 | 106 | [source,console] 107 | ---- 108 | Changes not staged for commit: 109 | (use "git add ..." to update what will be committed) 110 | (use "git checkout -- ..." to discard changes in working directory) 111 | 112 | modified: CONTRIBUTING.md 113 | ---- 114 | 115 | 它非常清楚地告诉了你如何撤消之前所做的修改。 116 | 让我们来按照提示执行: 117 | 118 | [source,console] 119 | ---- 120 | $ git checkout -- CONTRIBUTING.md 121 | $ git status 122 | On branch master 123 | Changes to be committed: 124 | (use "git reset HEAD ..." to unstage) 125 | 126 | renamed: README.md -> README 127 | 128 | ---- 129 | 130 | 可以看到那些修改已经被撤消了。 131 | 132 | [IMPORTANT] 133 | ===== 134 | 请务必记得 `git checkout -- ` 是一个危险的命令。 135 | 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 136 | 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。 137 | ===== 138 | 139 | 如果你仍然想保留对那个文件做出的修改,但是现在仍然需要撤消,我们将会在 140 | <> 介绍保存进度与分支,这通常是更好的做法。 141 | 142 | 记住,在 Git 中任何 *已提交* 的东西几乎总是可以恢复的。 143 | 甚至那些被删除的分支中的提交或使用 `--amend` 选项覆盖的提交也可以恢复 144 | (阅读 <> 了解数据恢复)。 145 | 然而,任何你未提交的东西丢失后很可能再也找不到了。 146 | -------------------------------------------------------------------------------- /images/head-to-testing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/head-to-testing 9 | 10 | 11 | 12 | 13 | images/head-to-testing 14 | Created with Sketch. 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | master 23 | 24 | 25 | 26 | testing 27 | 28 | 29 | 30 | f30ab 31 | 32 | 33 | 34 | 34ac2 35 | 36 | 37 | 38 | 98ca9 39 | 40 | 41 | 42 | 43 | HEAD 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /images/rerere1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/rerere1 9 | 10 | 11 | 12 | 13 | images/rerere1 14 | Created with Sketch. 15 | 16 | 17 | 18 | 19 | 20 | master 21 | 22 | 23 | 24 | 25 | 26 | 27 | hello world 28 | 29 | 30 | 31 | 32 | 33 | 34 | hola world 35 | 36 | 37 | 38 | 39 | 40 | 41 | hello mundo 42 | 43 | 44 | 45 | 46 | 47 | 48 | i18-world 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /images/basic-branching-3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/basic-branching-3 9 | 10 | 11 | 12 | 13 | images/basic-branching-3 14 | Created with Sketch. 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | C0 24 | 25 | 26 | 27 | C1 28 | 29 | 30 | 31 | C2 32 | 33 | 34 | 35 | C3 36 | 37 | 38 | 39 | 40 | master 41 | 42 | 43 | 44 | 45 | 46 | iss53 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /images/head-to-master.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/head-to-master 9 | 10 | 11 | 12 | 13 | images/head-to-master 14 | Created with Sketch. 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | master 24 | 25 | 26 | 27 | testing 28 | 29 | 30 | 31 | f30ab 32 | 33 | 34 | 35 | 34ac2 36 | 37 | 38 | 39 | 98ca9 40 | 41 | 42 | 43 | HEAD 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /images/advance-testing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | images/advance-testing 9 | 10 | 11 | 12 | images/advance-testing 13 | Created with Sketch. 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | master 23 | 24 | 25 | 26 | 27 | f30ab 28 | 29 | 30 | 31 | 87ab2 32 | 33 | 34 | 35 | 34ac2 36 | 37 | 38 | 39 | 98ca9 40 | 41 | 42 | 43 | 44 | 45 | testing 46 | 47 | 48 | 49 | 50 | HEAD 51 | 52 | 53 | -------------------------------------------------------------------------------- /book/10-git-internals/sections/refspec.asc: -------------------------------------------------------------------------------- 1 | [[_refspec]] 2 | === 引用规范 3 | 4 | 纵观全书,我们已经使用过一些诸如远程分支到本地引用的简单映射方式,但这种映射可以更复杂。 5 | 假设你已经跟着前几节在本地创建了一个小的 Git 仓库,现在想要添加一个远程仓库: 6 | 7 | [source,console] 8 | ---- 9 | $ git remote add origin https://github.com/schacon/simplegit-progit 10 | ---- 11 | 12 | 运行上述命令会在你仓库中的 `.git/config` 文件中添加一个小节, 13 | 并在其中指定远程版本库的名称(`origin`)、URL 和一个用于获取操作的 *引用规范(refspec)*: 14 | 15 | [source,ini] 16 | ---- 17 | [remote "origin"] 18 | url = https://github.com/schacon/simplegit-progit 19 | fetch = +refs/heads/*:refs/remotes/origin/* 20 | ---- 21 | 22 | 引用规范的格式由一个可选的 `+` 号和紧随其后的 `:` 组成, 23 | 其中 `` 是一个模式(pattern),代表远程版本库中的引用; 24 | `` 是本地跟踪的远程引用的位置。 25 | `+` 号告诉 Git 即使在不能快进的情况下也要(强制)更新引用。 26 | 27 | 默认情况下,引用规范由 `git remote add origin` 命令自动生成, 28 | Git 获取服务器中 `refs/heads/` 下面的所有引用,并将它写入到本地的 `refs/remotes/origin/` 中。 29 | 所以,如果服务器上有一个 `master` 分支,你可以在本地通过下面任意一种方式来访问该分支上的提交记录: 30 | 31 | [source,console] 32 | ---- 33 | $ git log origin/master 34 | $ git log remotes/origin/master 35 | $ git log refs/remotes/origin/master 36 | ---- 37 | 38 | 上面的三个命令作用相同,因为 Git 会把它们都扩展成 `refs/remotes/origin/master`。 39 | 40 | 如果想让 Git 每次只拉取远程的 `master` 分支,而不是所有分支, 41 | 可以把(引用规范的)获取那一行修改为只引用该分支: 42 | 43 | [source] 44 | ---- 45 | fetch = +refs/heads/master:refs/remotes/origin/master 46 | ---- 47 | 48 | 这仅是针对该远程版本库的 `git fetch` 操作的默认引用规范。 49 | 如果有某些只希望被执行一次的操作,我们也可以在命令行指定引用规范。 50 | 若要将远程的 `master` 分支拉到本地的 `origin/mymaster` 分支,可以运行: 51 | 52 | [source,console] 53 | ---- 54 | $ git fetch origin master:refs/remotes/origin/mymaster 55 | ---- 56 | 57 | 你也可以指定多个引用规范。 58 | 在命令行中,你可以按照如下的方式拉取多个分支: 59 | 60 | [source,console] 61 | ---- 62 | $ git fetch origin master:refs/remotes/origin/mymaster \ 63 | topic:refs/remotes/origin/topic 64 | From git@github.com:schacon/simplegit 65 | ! [rejected] master -> origin/mymaster (non fast forward) 66 | * [new branch] topic -> origin/topic 67 | ---- 68 | 69 | 在这个例子中,对 `master` 分支的拉取操作被拒绝,因为它不是一个可以快进的引用。 70 | 我们可以通过在引用规范之前指定 `+` 号来覆盖该规则。 71 | 72 | 你也可以在配置文件中指定多个用于获取操作的引用规范。 73 | 如果想在每次从 `origin` 远程仓库获取时都包括 `master` 和 `experiment` 分支,添加如下两行: 74 | 75 | [source,ini] 76 | ---- 77 | [remote "origin"] 78 | url = https://github.com/schacon/simplegit-progit 79 | fetch = +refs/heads/master:refs/remotes/origin/master 80 | fetch = +refs/heads/experiment:refs/remotes/origin/experiment 81 | ---- 82 | 83 | 自 Git 2.6.0 起可以在模式中使用部分通配符以匹配多个分支,所以这样是可以工作的: 84 | 85 | [source,ini] 86 | ---- 87 | fetch = +refs/heads/qa*:refs/remotes/origin/qa* 88 | ---- 89 | 90 | 更棒的是,我们可以使用命名空间(或目录)来实现相同的目标,并且更具结构性。 91 | 假设你有一个 QA 团队,他们推送了一系列分支,同时你只想要获取 `master` 和 92 | QA 团队的所有分支而不关心其他任何分支,那么可以使用如下配置: 93 | 94 | [source,ini] 95 | ---- 96 | [remote "origin"] 97 | url = https://github.com/schacon/simplegit-progit 98 | fetch = +refs/heads/master:refs/remotes/origin/master 99 | fetch = +refs/heads/qa/*:refs/remotes/origin/qa/* 100 | ---- 101 | 102 | 如果项目的工作流很复杂,有 QA 团队推送分支、开发人员推送分支、集成团队推送并且在远程分支上展开协作,你就可以像这样(在本地)为这些分支创建各自的命名空间,非常方便。 103 | 104 | [[_pushing_refspecs]] 105 | ==== 引用规范推送 106 | 107 | 像上面这样从远程版本库获取已在命名空间中的引用当然很棒,但 QA 团队最初应该如何将他们的分支放入远程的 `qa/` 命名空间呢? 108 | 我们可以通过引用规范推送来完成这个任务。 109 | 110 | 如果 QA 团队想把他们的 `master` 分支推送到远程服务器的 `qa/master` 分支上,可以运行: 111 | 112 | [source,console] 113 | ---- 114 | $ git push origin master:refs/heads/qa/master 115 | ---- 116 | 117 | 如果他们希望 Git 每次运行 `git push origin` 时都像上面这样推送,可以在他们的配置文件中添加一条 `push` 值: 118 | 119 | [source,ini] 120 | ---- 121 | [remote "origin"] 122 | url = https://github.com/schacon/simplegit-progit 123 | fetch = +refs/heads/*:refs/remotes/origin/* 124 | push = refs/heads/master:refs/heads/qa/master 125 | ---- 126 | 127 | 正如刚才所指出的,这会让 `git push origin` 默认把本地 `master` 分支推送到远程 `qa/master` 分支。 128 | 129 | [NOTE] 130 | ==== 131 | 你无法通过引用规范从一个仓库获取并推送到另一个仓库。 132 | 这样做的示例见 <>。 133 | ==== 134 | 135 | ==== 删除引用 136 | 137 | 你还可以借助类似下面的命令通过引用规范从远程服务器上删除引用: 138 | 139 | [source,console] 140 | ---- 141 | $ git push origin :topic 142 | ---- 143 | 144 | 因为引用规范(的格式)是 `:`,所以上述命令把 `` 留空,意味着把远程版本库的 `topic` 分支定义为空值,也就是删除它。 145 | 146 | 或者你可以使用更新的语法(自 Git v1.7.0 以后可用): 147 | 148 | [source,console] 149 | ---- 150 | $ git push origin --delete topic 151 | ---- 152 | -------------------------------------------------------------------------------- /book/09-git-and-other-scms/sections/import-svn.asc: -------------------------------------------------------------------------------- 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 --quiet | grep author | sort -u | \ 26 | perl -pe 's/.*>(.*?)<.*/$1 = /' 27 | ---- 28 | 29 | 这会将日志输出为 XML 格式,然后保留作者信息行、去除重复、去除 XML 标记。 30 | 很显然这只会在安装了 `grep`、`sort` 与 `perl` 的机器上运行。 31 | 然后,将输出重定向到你的 `users.txt` 文件中,这样就可以在每一个记录后面加入对应的 Git 用户数据。 32 | 33 | [NOTE] 34 | ==== 35 | 如果你在 Windows 上运行它,那么到这里就会遇到问题。微软提供了一些不错的建议和示例: 36 | https://docs.microsoft.com/en-us/azure/devops/repos/git/perform-migration-from-svn-to-git[]. 37 | ==== 38 | 39 | 你可以将此文件提供给 `git svn` 来帮助它更加精确地映射作者数据。 40 | 也可以通过传递 `--no-metadata` 给 `clone` 与 `init` 命令,告诉 `git svn` 不要包括 41 | Subversion 通常会导入的元数据。在导入过程中,Git 会在每个提交说明的元数据中生成一个 42 | `git-svn-id`。 43 | 44 | [NOTE] 45 | ==== 46 | 当你想要将 Git 仓库中的提交镜像回原 SVN 仓库中时,需要保留元数据。 47 | 如果你不想在提交记录中同步它,请直接省略掉 `--no-metadata` 选项。 48 | ==== 49 | 50 | 这会使你的 `import` 命令看起来像这样: 51 | 52 | [source,console] 53 | ---- 54 | $ git svn clone http://my-project.googlecode.com/svn/ \ 55 | --authors-file=users.txt --no-metadata --prefix "" -s my_project 56 | $ cd my_project 57 | ---- 58 | 59 | 现在在 `my_project` 目录中应当有了一个更好的 Subversion 导入。 60 | 并不像是下面这样的提交: 61 | 62 | [source] 63 | ---- 64 | commit 37efa680e8473b615de980fa935944215428a35a 65 | Author: schacon 66 | Date: Sun May 3 00:12:22 2009 +0000 67 | 68 | fixed install - go to trunk 69 | 70 | git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de- 71 | be05-5f7a86268029 72 | ---- 73 | 74 | 反而它们看起来像是这样: 75 | 76 | [source] 77 | ---- 78 | commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2 79 | Author: Scott Chacon 80 | Date: Sun May 3 00:12:22 2009 +0000 81 | 82 | fixed install - go to trunk 83 | ---- 84 | 85 | 不仅是 Author 字段更好看了,`git-svn-id` 也不在了。 86 | 87 | 之后,你应当做一些导入后的清理工作。 88 | 第一步,你应当清理 `git svn` 设置的奇怪的引用。 89 | 首先移动标签,这样它们就是标签而不是奇怪的远程引用,然后你会移动剩余的分支这样它们就是本地的了。 90 | 91 | 为了将标签变为合适的 Git 标签,运行: 92 | 93 | [source,console] 94 | ---- 95 | $ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done 96 | ---- 97 | 98 | 这会使原来在 `refs/remotes/tags/` 里的远程分支引用变成真正的(轻量)标签。 99 | 100 | 接下来,将 `refs/remotes` 下剩余的引用移动为本地分支: 101 | 102 | [source,console] 103 | ---- 104 | $ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done 105 | ---- 106 | 107 | 你可能会看到一些额外的分支,这些分支的后缀是 `@xxx` (其中 xxx 是一个数字),而在 Subversion 中你只会看到一个分支。这实际上是 Subversion 一个叫做“peg-revisions”的功能,Git在语法上没有与之对应的功能。因此, `git svn` 只是简单地将 SVN peg-revision 版本号添加到分支名称中,这同你在 SVN 中修改分支名称来定位一个分支的“peg-revision”是一样的。如果你对于 peg-revisions 完全不在乎,通过下面的命令可以轻易地移除他们: 108 | 109 | [source,console] 110 | ---- 111 | $ for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done 112 | ---- 113 | 114 | 现在所有的旧分支都是真正的 Git 分支,并且所有的旧标签都是真正的 Git 标签。 115 | 116 | 还有最后一点东西需要清理。`git svn` 会创建一个名为 `trunk` 的额外分支,它对应于 117 | Subversion 的默认分支,然而 `trunk` 引用和 `master` 指向同一个位置。 118 | 鉴于在 Git 中 `master` 最为常用,因此我们可以移除额外的分支: 119 | 120 | [source,console] 121 | ---- 122 | $ git branch -d trunk 123 | ---- 124 | 125 | 最后一件要做的事情是,将你的新 Git 服务器添加为远程仓库并推送到上面。 126 | 下面是一个将你的服务器添加为远程仓库的例子: 127 | 128 | [source,console] 129 | ---- 130 | $ git remote add origin git@my-git-server:myrepository.git 131 | ---- 132 | 133 | 因为想要上传所有分支与标签,你现在可以运行: 134 | 135 | [source,console] 136 | ---- 137 | $ git push origin --all 138 | $ git push origin --tags 139 | ---- 140 | 141 | 通过以上漂亮、干净地导入操作,你的所有分支与标签都应该在新 Git 服务器上。 142 | --------------------------------------------------------------------------------