diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index c1b1a0a70..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - - - - - - - - - - - - -**Which version of the book is affected?** - - - -**Describe the bug:** - - -**Steps to reproduce:** - - - - - - -**Expected behavior:** - - -**Screenshots:** - - -**Additional context:** - - - -**Desktop:** - - -- Operating system: -- Browser/application: -- Browser/application version: - -**Smartphone:** - - -- Device: -- OS: -- Browser/application: -- Browser/application version: - -**E-book reader:** - - -- Device: -- Software Update: diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..6660cdf8d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,131 @@ +name: Bug report +description: Create a report to help us improve +labels: ["bug"] +body: + - type: checkboxes + attributes: + label: There's no existing/similar bug report. + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + + - type: checkboxes + attributes: + label: This report is about a single actionable bug. + description: Please create one issue per bug, split up your bug reports if needed. + options: + - label: I'm reporting a single actionable bug + required: true + + - type: checkboxes + attributes: + label: This report is about the ProGit book, version 2, English language. + description: Bug reports about translations or the first version of the book are not accepted. + options: + - label: This bug is not about a translation or old version + required: true + + - type: checkboxes + attributes: + label: Bug covers book website/pdf + description: This bug is about the book as found on the [website](https://www.git-scm.com/book/en/v2) or the PDF. + options: + - label: I confirm the bug is about the book as found on the website/pdf + validations: + required: false + + - type: checkboxes + attributes: + label: Problem is present in the Pro Git book on the website? + description: If you found an issue in the pdf/epub/mobi files, you've checked if the problem is also present in the Pro Git book on the [website](https://www.git-scm.com/book/en/v2). + options: + - label: This bug also affects the Pro Git book as published on the website. + validations: + required: false + + - type: dropdown + attributes: + label: Which version of the book is affected? + description: | + It's important for us to know if the problem is in the source or in the tooling that creates the pdf/epub/mobi files. + Therefore, please select which versions are affected. + options: + - "Source files" + - "Tooling" + - "Source files and tooling" + - "I don't know" + validations: + required: true + + - type: textarea + attributes: + label: "Describe the bug:" + description: A clear and concise description of what the bug is. + validations: + required: true + + - type: textarea + attributes: + label: "Steps to reproduce:" + description: Please write the steps needed to reproduce the bug here. + placeholder: Provide a ordered list of steps to reproduce. + value: | + 1. Go to '...' + 2. Click on '...' + 3. 'Scroll down to '...' + 4. See error + validations: + required: true + + - type: textarea + attributes: + label: "Expected behavior:" + description: A clear and concise description of what you expected to happen. + placeholder: I expected ... to happen. + validations: + required: true + + - type: textarea + attributes: + label: "Screenshots:" + description: If applicable, add screenshots to help explain your problem. + placeholder: "Tip: you can drag your screenshot into this field, or you can copy/paste." + validations: + required: false + + - type: textarea + attributes: + label: "Additional context:" + description: | + Add any other context about the problem here. + You can also put references to similar bugs here. + placeholder: "Example: this bug also affect issues #1 and #2." + validations: + required: false + + - type: input + attributes: + label: Device + description: Tell us what kind of device you're using to access the content. + placeholder: mobile device / desktop / laptop / e-book reader + validations: + required: false + + - type: input + attributes: + label: Operating system + description: If the problem is with the book or the published files, we need to know what operating system you run on your device. + placeholder: | + Windows 10 Home Edition + validations: + required: false + + - type: input + attributes: + label: Browser/application + version + description: What browser/application are you using? We also need the version number of the browser/application. + placeholder: | + Google Chrome 91.0.4472.164 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..e8a3cd746 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,17 @@ +blank_issues_enabled: true +contact_links: + - name: Translation bug + url: https://github.com/progit/progit2/blob/main/TRANSLATING.md + about: Refer to this table to find out where to report translation bugs. + + - name: Report bugs for git-scm.com site + url: https://github.com/git/git-scm.com/issues/ + about: Please report problems with the git-scm.com site there. + + - name: Bug is about Git program itself + url: https://git-scm.com/community + about: Please report problems with the Git program there. + + - name: Bug is about Git for Windows + url: https://github.com/git-for-windows/git/issues + about: Please report problems with Git for Windows there. diff --git a/.github/ISSUE_TEMPLATE/enhancement_idea.yml b/.github/ISSUE_TEMPLATE/enhancement_idea.yml new file mode 100644 index 000000000..f0b19c19f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement_idea.yml @@ -0,0 +1,34 @@ +name: Enhancement idea +description: Suggest an idea for the ProGit2 book or repository +labels: ["enhancement"] +body: + - type: textarea + attributes: + label: General overview of your idea. + description: Give a general overview of your idea. + validations: + required: true + + - type: textarea + attributes: + label: What problem will this solve? + description: Explain what problem you're trying to solve. + validations: + required: true + + - type: textarea + attributes: + label: Have you thought about other solutions? + description: Describe any alternative solutions to the problem. + validations: + required: false + + - type: dropdown + attributes: + label: Do you want to help with this enhancement idea? + options: + - "Yes" + - "Maybe" + - "No" + validations: + required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..6adcdcdbe --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +version: 2 +updates: + # Maintain dependencies for Ruby + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily" # Checks on Monday through Friday. + + # Maintain GitHub Action runners + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" # Checks on Monday through Friday. + + # Set default reviewer and labels + reviewers: + - "ben" + labels: + - "dependabot" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..fde92545c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ + + + + + +- [ ] I provide my work under the [project license](https://github.com/progit/progit2/blob/main/LICENSE.asc). +- [ ] I grant such license of my work as is required for the purposes of future print editions to [Ben Straub](https://github.com/ben) and [Scott Chacon](https://github.com/schacon). + +## Changes + +- + +## Context + diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml new file mode 100644 index 000000000..f7fed92b5 --- /dev/null +++ b/.github/workflows/pr-build.yml @@ -0,0 +1,20 @@ +name: Pull Request Build + +on: + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.1 + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Build book + run: bundle exec rake book:build diff --git a/.github/workflows/release-on-merge.yml b/.github/workflows/release-on-merge.yml new file mode 100644 index 000000000..c0ece1877 --- /dev/null +++ b/.github/workflows/release-on-merge.yml @@ -0,0 +1,38 @@ +name: Release on push to main + +on: + push: + branches: [ main ] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.1 + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Build release assets + run: bundle exec rake book:build + + - name: Compute tag name + id: compute-tag + run: | + echo Computing next tag number + LASTPATCH=$(git describe --tags | cut -d- -f1 | cut -d. -f3) + PATCH=$(($LASTPATCH+1)) + echo "tagname=2.1.${PATCH}" >> $GITHUB_OUTPUT + + - name: Create release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ steps.compute-tag.outputs.tagname }} + commit: main + artifacts: './progit.epub,./progit.fb2.zip,./progit.mobi,./progit.pdf,./progit.html' diff --git a/.gitignore b/.gitignore index 424a30e52..aa9b3a0a0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ progit.html progit.pdf progit.pdfmarks progit.epub +progit.fb2.zip progit-kf8.epub progit.mobi contributors.txt \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 17a10e01d..000000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: ruby -git: - depth: false -cache: bundler -before_install: -- bundle install -after_success: -- script/tag_on_master -script: bundle exec rake book:build -env: - secure: "O+YCTDgLfCYAJjjOv2sApDRV5NJe6pkhiYIkORFuf2flO8HE72fEtDRpSWh1vulnIH6AjRK2jH7C8qA3MVbUO8D0io+Ha+vnbMXIp1JPCptcJNEkJrW13VTR66SWOzsgLp3mCrIC+YdE2JoYWGcnDsRMQwdnrWnxBzSOd22ZKzU=" - -before_deploy: bundle install && bundle exec rake book:build -deploy: - provider: releases - file: - - progit.epub - - progit.mobi - - progit.pdf - skip_cleanup: true - on: - tags: true - api-key: - secure: "l3XdupX6dT48IoTieJXrd7Yx8+KhiR2QYrNrDzT6RKxA7UyXGSP/axsVerg7OjKfIHWZgDJRVzcc2RswE+Xjw9sOY8r2h2q9uCwj8G0EqtFbtgGK0La5LB0euh0tNJN8GLFj1OdSZGY7dWWK88GXeHCua2WSify0V79R4ClIM+s=" -branches: - only: - - master - - /^2\.1(\.\d+)+$/ - -notifications: - email: - on_success: never - on_failure: always diff --git a/A-git-in-other-environments.asc b/A-git-in-other-environments.asc index 496af0a65..32d7f6168 100644 --- a/A-git-in-other-environments.asc +++ b/A-git-in-other-environments.asc @@ -13,7 +13,7 @@ include::book/A-git-in-other-environments/sections/visualstudio.asc[] include::book/A-git-in-other-environments/sections/visualstudiocode.asc[] -include::book/A-git-in-other-environments/sections/eclipse.asc[] +include::book/A-git-in-other-environments/sections/jetbrainsides.asc[] include::book/A-git-in-other-environments/sections/sublimetext.asc[] diff --git a/B-embedding-git-in-your-applications.asc b/B-embedding-git-in-your-applications.asc index 782e177de..f3e602979 100644 --- a/B-embedding-git-in-your-applications.asc +++ b/B-embedding-git-in-your-applications.asc @@ -17,4 +17,3 @@ include::book/B-embedding-git/sections/jgit.asc[] include::book/B-embedding-git/sections/go-git.asc[] include::book/B-embedding-git/sections/dulwich.asc[] - diff --git a/C-git-commands.asc b/C-git-commands.asc index 893ae811a..3e3523ef7 100644 --- a/C-git-commands.asc +++ b/C-git-commands.asc @@ -8,6 +8,13 @@ However, this leaves us with examples of usage of the commands somewhat scattere In this appendix, we'll go through all the Git commands we addressed throughout the book, grouped roughly by what they're used for. We'll talk about what each command very generally does and then point out where in the book you can find us having used it. +[TIP] +==== +You can abbreviate long options. +For example, you can type in `git commit --a`, which acts as if you typed `git commit --amend`. +This only works when the letters after `--` are unique for one option. +Do use the full option when writing scripts. +==== === Setup and Config @@ -34,6 +41,44 @@ In <> we showed how to set up smudge an Finally, basically the entirety of <> is dedicated to the command. +[[ch_core_editor]] +==== git config core.editor commands + +Accompanying the configuration instructions in <>, many editors can be set as follows: + +.Exhaustive list of `core.editor` configuration commands +[cols="1,2",options="header"] +|============================== +|Editor | Configuration command +|Atom |`git config --global core.editor "atom --wait"` +|BBEdit (macOS, with command line tools) |`git config --global core.editor "bbedit -w"` +|Emacs |`git config --global core.editor emacs` +|Gedit (Linux) |`git config --global core.editor "gedit --wait --new-window"` +|Gvim (Windows 64-bit) |`git config --global core.editor "'C:\Program Files\Vim\vim72\gvim.exe' --nofork '%*'"` (Also see note below) +|Helix |`git config --global core.editor "hx"` +|Kate (Linux) |`git config --global core.editor "kate --block"` +|nano |`git config --global core.editor "nano -w"` +|Notepad (Windows 64-bit) |`git config core.editor notepad` +|Notepad++ (Windows 64-bit) |`git config --global core.editor "'C:\Program Files\Notepad+\+\notepad++.exe' -multiInst -notabbar -nosession -noPlugin"` (Also see note below) +|Scratch (Linux)|`git config --global core.editor "scratch-text-editor"` +|Sublime Text (macOS) |`git config --global core.editor "/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl --new-window --wait"` +|Sublime Text (Windows 64-bit) |`git config --global core.editor "'C:\Program Files\Sublime Text 3\sublime_text.exe' -w"` (Also see note below) +|TextEdit (macOS)|`git config --global core.editor "open --wait-apps --new -e"` +|Textmate |`git config --global core.editor "mate -w"` +|Textpad (Windows 64-bit) |`git config --global core.editor "'C:\Program Files\TextPad 5\TextPad.exe' -m"` (Also see note below) +|UltraEdit (Windows 64-bit) | `git config --global core.editor Uedit32` +|Vim |`git config --global core.editor "vim --nofork"` +|Visual Studio Code |`git config --global core.editor "code --wait"` +|VSCodium (Free/Libre Open Source Software Binaries of VSCode) | `git config --global core.editor "codium --wait"` +|WordPad |`git config --global core.editor "'C:\Program Files\Windows NT\Accessories\wordpad.exe'"` +|Xi | `git config --global core.editor "xi --wait"` +|============================== + +[NOTE] +==== +If you have a 32-bit editor on a Windows 64-bit system, the program will be installed in `C:\Program Files (x86)\` rather than `C:\Program Files\` as in the table above. +==== + ==== git help The `git help` command is used to show you all the documentation shipped with Git about any command. @@ -41,7 +86,6 @@ While we're giving a rough overview of most of the more popular ones in this app We introduced the `git help` command in <> and showed you how to use it to find more information about the `git shell` in <>. - === Getting and Creating Projects There are two ways to get a Git repository. @@ -53,7 +97,7 @@ To take a directory and turn it into a new Git repository so you can start versi We first introduce this in <>, where we show creating a brand new repository to start working with. -We talk briefly about how you can change the default branch from ``master'' in <>. +We talk briefly about how you can change the default branch name from "`master`" in <>. We use this command to create an empty bare repository for a server in <>. @@ -76,14 +120,13 @@ Finally, in <> we learn the `--recurse-submo Though it's used in many other places through the book, these are the ones that are somewhat unique or where it is used in ways that are a little different. - === Basic Snapshotting For the basic workflow of staging content and committing it to your history, there are only a few basic commands. ==== git add -The `git add` command adds content from the working directory into the staging area (or ``index'') for the next commit. +The `git add` command adds content from the working directory into the staging area (or "`index`") for the next commit. When the `git commit` command is run, by default it only looks at this staging area, so `git add` is used to craft what exactly you would like your next commit snapshot to look like. This command is an incredibly important command in Git and is mentioned or used dozens of times in this book. @@ -269,7 +312,6 @@ This command is introduced and covered in detail in <>. - === Sharing and Updating Projects There are not very many commands in Git that access the network, nearly all of the commands operate on the local database. @@ -323,7 +365,7 @@ This can help you be very specific about what work you wish to share. ==== git remote The `git remote` command is a management tool for your record of remote repositories. -It allows you to save long URLs as short handles, such as ``origin'' so you don't have to type them out all the time. +It allows you to save long URLs as short handles, such as "`origin`" so you don't have to type them out all the time. You can have several of these and the `git remote` command is used to add, change and delete them. This command is covered in detail in <>, including listing, adding, removing and renaming them. @@ -371,7 +413,6 @@ It's a way to get a description of a commit that is as unambiguous as a commit S We use `git describe` in <> and <> to get a string to name our release file after. - === Debugging Git has a couple of commands that are used to help debug an issue in your code. @@ -499,7 +540,7 @@ If you're administering a Git repository or need to fix something in a big way, ==== git gc -The `git gc` command runs ``garbage collection'' on your repository, removing unnecessary files in your database and packing up the remaining files into a more efficient format. +The `git gc` command runs "`garbage collection`" on your repository, removing unnecessary files in your database and packing up the remaining files into a more efficient format. This command normally runs in the background for you, though you can manually run it if you wish. We go over some examples of this in <>. @@ -524,8 +565,7 @@ The `git filter-branch` command is used to rewrite loads of commits according to In <> we explain the command and explore several different options such as `--commit-filter`, `--subdirectory-filter` and `--tree-filter`. -In <> and <> we use it to fix up imported external repositories. - +In <> we use it to fix up imported external repositories. === Plumbing Commands diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..b311dcddc --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,29 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: Pro Git +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - given-names: Scott + family-names: Chacon + email: schacon@gmail.com + - given-names: Ben + family-names: Straub + email: ben@straub.cc +identifiers: + - type: url + value: 'https://git-scm.com/book/en/v2' + description: Pro Git website +repository-code: 'https://github.com/progit/progit2' +url: 'https://git-scm.com/book/en/v2' +keywords: + - git + - book + - asciidoc + - pro-git +license: CC-BY-NC-SA-3.0 +version: '2' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c977233c2..ba00b375c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,44 +1,44 @@ # Contributing to Pro Git (2nd Edition) -## Licensing +## Licensing your work to us -By opening a pull request to this repository, you agree to provide your work under the [project license](LICENSE.asc). +When you open a pull request, you agree to provide your work under the [project license](LICENSE.asc). Also, you agree to grant such license of your work as is required for the purposes of future print editions to @ben and @schacon. Should your changes appear in a printed edition, you'll be included in the [contributors list](book/contributors.asc). ## Signaling an Issue -Before signaling an issue, please check that there isn't already a similar one in the bug tracking system. +Search for similar issues, before creating a new issue. -Also, if this issue has been spotted on the git-scm.com site, please cross-check that it is still present in the pdf version. -The issue may have already been corrected, but the changes have not been deployed yet. +Also, if this issue has been spotted on the git-scm.com site, cross-check that the issue is present in the pdf version. +The issue may have already been corrected in the source files, but not yet deployed to the git-scm.com site. ## Small Corrections Errata and basic clarifications will be accepted if we agree that they improve the content. -You can also open an issue so we can figure out how or if it needs to be addressed. +You can also open an issue so that we can discuss how or if the issue needs to be addressed. -If you've never done this before, the [flow guide](https://guides.github.com/introduction/flow/) might be useful. +If you've never done this before, the [flow guide](https://docs.github.com/en/get-started/quickstart/github-flow) might be useful. ## Large Rewrites Open an issue for discussion before you start. -These changes tend to be very subjective, often only clarifying things for some small percentage of people and it's rarely worth the time to accept them. -Professional copy editors have already reviewed this content multiple times so while you may have somewhat better taste and grammar than we do it's unlikely that your prose is going to be *so* much better that it's worth changing vast swaths of text. +A large rewrite tends to be very subjective, often only clarifying things for a small amount of readers. +Professional copy editors have already reviewed this content multiple times. +It's unlikely that your prose is going to be *so* much better that it's worth changing large portions of text. ## Figures -The images in this book were generated using [Sketch 3](https://www.sketchapp.com/), with the [included sketchbook file](diagram-source/progit.sketch). +The images in this book are generated using [Sketch 3](https://www.sketch.com/), with the [included sketchbook file](diagram-source/progit.sketch). -To add a figure: +To create a figure: 1. Add a page to the sketchbook. -Try to use the included symbols wherever possible. +Use the included symbols wherever possible. 2. Add a "slice" to your page. -Give it a name that matches the destination PNG filename, relative from the root of the source directory. -3. Make sure your slice is set to export at "800w". - +Name the slice so that it matches the destination PNG filename, relative from the root of the source directory. +3. Set your slice to export at "800w". ## Translations -If you would like to contribute to translating Pro Git into your language, take a look at [TRANSLATING.md](TRANSLATING.md). +If you want to contribute to translating Pro Git into your language, take a look at [TRANSLATING.md](TRANSLATING.md). diff --git a/Gemfile b/Gemfile index 4ecffb4fd..0893f08a4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,18 @@ source 'https://rubygems.org' -gem 'rake' -gem 'asciidoctor', '1.5.6.1' +gem 'rake', '13.2.1' +gem 'asciidoctor', '2.0.22' -gem 'json' -gem 'awesome_print' +gem 'json', '2.9.1' +gem 'awesome_print', '1.9.2' -gem 'asciidoctor-epub3', :git => 'https://github.com/asciidoctor/asciidoctor-epub3' -gem 'asciidoctor-pdf', '1.5.0.alpha.16' +gem 'asciidoctor-fb2', '0.7.0' +gem 'asciidoctor-epub3', '2.1.3' +gem 'asciidoctor-pdf', '2.3.17' -gem 'coderay' -gem 'pygments.rb' -gem 'thread_safe' -gem 'epubcheck' -gem 'kindlegen' +gem 'coderay', '1.1.3' +gem 'pygments.rb', '2.4.1' +gem 'thread_safe', '0.3.6' +gem 'epubcheck-ruby', '5.2.0.0' +gem 'html-proofer', '5.0.9' +gem 'kindlegen', '3.1.1' diff --git a/README.asc b/README.asc index d3728c4ee..54e480ded 100644 --- a/README.asc +++ b/README.asc @@ -7,7 +7,7 @@ You can find this book online at: https://git-scm.com/book Like the first edition, the second edition of Pro Git is open source under a Creative Commons license. A couple of things have changed since open sourcing the first edition. -For one, we've moved from Markdown to the amazing Asciidoc format for the text of the book. +For one, we've moved from Markdown to the amazing AsciiDoc format for the text of the book; here's an https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/[AsciiDoc quick reference]. We've also moved to keeping the translations in separate repositories rather than subdirectories of the English repository. See link:TRANSLATING.md[the translating document] for more information. @@ -30,6 +30,33 @@ Converting to PDF... -- PDF output at progit.pdf ---- +You can generate just one of the supported formats (HTML, EPUB, mobi, or PDF). +Use one of the following commands: + +To generate the HTML book: + +---- +$ bundle exec rake book:build_html +---- + +To generate the EPUB book: + +---- +$ bundle exec rake book:build_epub +---- + +To generate the mobi book: + +---- +$ bundle exec rake book:build_mobi +---- + +To generate the PDF book: + +---- +$ bundle exec rake book:build_pdf +---- + == Signaling an Issue Before signaling an issue, please check that there isn't already a similar one in the bug tracking system. diff --git a/Rakefile b/Rakefile index 5b5702aaa..4f7c3dac9 100644 --- a/Rakefile +++ b/Rakefile @@ -1,35 +1,138 @@ namespace :book do - desc 'build basic book formats' - task :build do - begin - version_string = ENV['TRAVIS_TAG'] || `git describe --tags`.chomp - if version_string.empty? - version_string = '0' + # Variables referenced for build + version_string = `git describe --tags --abbrev=0`.chomp + if version_string.empty? + version_string = '0' + else + versions = version_string.split('.') + version_string = versions[0] + '.' + versions[1] + '.' + versions[2].to_i.next.to_s + end + date_string = Time.now.strftime('%Y-%m-%d') + params = "--attribute revnumber='#{version_string}' --attribute revdate='#{date_string}'" + header_hash = `git rev-parse --short HEAD`.strip + + # Check contributors list + # This checks commit hash stored in the header of list against current HEAD + def check_contrib + if File.exist?('book/contributors.txt') + current_head_hash = `git rev-parse --short HEAD`.strip + header = `head -n 1 book/contributors.txt`.strip + # Match regex, then coerce resulting array to string by join + header_hash = header.scan(/[a-f0-9]{7,}/).join + + if header_hash == current_head_hash + puts "Hash on header of contributors list (#{header_hash}) matches the current HEAD (#{current_head_hash})" + else + puts "Hash on header of contributors list (#{header_hash}) does not match the current HEAD (#{current_head_hash}), refreshing" + sh "rm book/contributors.txt" + # Reenable and invoke task again + Rake::Task['book/contributors.txt'].reenable + Rake::Task['book/contributors.txt'].invoke end - date_string = Time.now.strftime("%Y-%m-%d") - params = "--attribute revnumber='#{version_string}' --attribute revdate='#{date_string}'" - puts "Generating contributors list" - `git shortlog -s | grep -v -E "(Straub|Chacon)" | cut -f 2- | column -c 120 > book/contributors.txt` + end + end + + desc 'build basic book formats' + task :build => [:build_html, :build_epub, :build_fb2, :build_mobi, :build_pdf] do + begin + # Run check + Rake::Task['book:check'].invoke + + # Rescue to ignore checking errors + rescue => e + puts e.message + puts 'Error when checking books (ignored)' + end + end + + desc 'build basic book formats (for ci)' + task :ci => [:build_html, :build_epub, :build_fb2, :build_mobi, :build_pdf] do + # Run check, but don't ignore any errors + Rake::Task['book:check'].invoke + end + + desc 'generate contributors list' + file 'book/contributors.txt' do + puts 'Generating contributors list' + sh "echo 'Contributors as of #{header_hash}:\n' > book/contributors.txt" + sh "git shortlog -s HEAD | grep -v -E '(Straub|Chacon|dependabot)' | cut -f 2- | sort | column -c 120 >> book/contributors.txt" + end + + desc 'build HTML format' + task :build_html => 'book/contributors.txt' do + check_contrib() + + puts 'Converting to HTML...' + sh "bundle exec asciidoctor #{params} -a data-uri progit.asc" + puts ' -- HTML output at progit.html' - puts "Converting to HTML..." - `bundle exec asciidoctor #{params} progit.asc` - puts " -- HTML output at progit.html" + end + + desc 'build Epub format' + task :build_epub => 'book/contributors.txt' do + check_contrib() + + puts 'Converting to EPub...' + sh "bundle exec asciidoctor-epub3 #{params} progit.asc" + puts ' -- Epub output at progit.epub' + + end - puts "Converting to EPub..." - `bundle exec asciidoctor-epub3 #{params} progit.asc` - puts " -- Epub output at progit.epub" + desc 'build FB2 format' + task :build_fb2 => 'book/contributors.txt' do + check_contrib() + + puts 'Converting to FB2...' + sh "bundle exec asciidoctor-fb2 #{params} progit.asc" + puts ' -- FB2 output at progit.fb2.zip' + + end + + desc 'build Mobi format' + task :build_mobi => 'book/contributors.txt' do + check_contrib() puts "Converting to Mobi (kf8)..." - `bundle exec asciidoctor-epub3 #{params} -a ebook-format=kf8 progit.asc` + sh "bundle exec asciidoctor-epub3 #{params} -a ebook-format=kf8 progit.asc" puts " -- Mobi output at progit.mobi" + end - puts "Converting to PDF... (this one takes a while)" - `bundle exec asciidoctor-pdf #{params} progit.asc 2>/dev/null` - puts " -- PDF output at progit.pdf" + desc 'build PDF format' + task :build_pdf => 'book/contributors.txt' do + check_contrib() + puts 'Converting to PDF... (this one takes a while)' + sh "bundle exec asciidoctor-pdf #{params} progit.asc 2>/dev/null" + puts ' -- PDF output at progit.pdf' + end + + desc 'Check generated books' + task :check => [:build_html, :build_epub] do + puts 'Checking generated books' + + sh "htmlproofer progit.html" + sh "epubcheck progit.epub" + end + + desc 'Clean all generated files' + task :clean do + begin + puts 'Removing generated files' + + FileList['book/contributors.txt', 'progit.html', 'progit-kf8.epub', 'progit.epub', 'progit.fb2.zip', 'progit.mobi', 'progit.pdf'].each do |file| + rm file + + # Rescue if file not found + rescue Errno::ENOENT => e + begin + puts e.message + puts 'Error removing files (ignored)' + end + end end end + end task :default => "book:build" diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..f1ed9cb69 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +## Reporting a security issue + +If you find any security issue or vulnerability, please email [ben@straub.cc](mailto:ben@straub.cc) with your report. + +Do not open a issue on the `progit/progit2` repository or discuss the vulnerability in public. diff --git a/TRANSLATING.md b/TRANSLATING.md index e7d630e52..1c8670925 100644 --- a/TRANSLATING.md +++ b/TRANSLATING.md @@ -8,9 +8,9 @@ Pro Git is a book about a technical tool, therefore translating it is difficult The following are guidelines to help you on your way: * Before you begin, read the whole Git Pro book in English, so that you're aware of the content, and are familiar with the style used. -* Ensure you have a good working knowledge of git, so that explaining the technical terms is doable. +* Ensure you have a good working knowledge of Git, so that explaining the technical terms is doable. * Stick to a common style and format for the translation. -* Be sure to read and understand the basics of [Asciidoc formatting](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/). Not following the asciidoc syntax can lead to problems with building/compilation of the pdf, epub and html files needed for the book. +* Be sure to read and understand the basics of [Asciidoc formatting](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/). Not following the asciidoc syntax can lead to problems with building/compilation of the pdf, epub and html files needed for the book. ## Translating the book to another language @@ -30,7 +30,7 @@ The following are guidelines to help you on your way: | Español | [progit/progit2-es](https://github.com/progit/progit2-es) | | فارسی | [progit2-fa/progit2](https://github.com/progit2-fa/progit2) | | Français | [progit/progit2-fr](https://github.com/progit/progit2-fr) | -| Deutsch | [progit-de/progit2](https://github.com/progit-de/progit2) | +| Deutsch | [progit/progit2-de](https://github.com/progit/progit2-de) | | Ελληνικά | [progit2-gr/progit2](https://github.com/progit2-gr/progit2) | | Indonesian | [progit/progit2-id](https://github.com/progit/progit2-id) | | Italiano | [progit/progit2-it](https://github.com/progit/progit2-it) | @@ -40,10 +40,11 @@ The following are guidelines to help you on your way: | Bahasa Melayu| [progit2-ms/progit2](https://github.com/progit2-ms/progit2) | | Nederlands | [progit/progit2-nl](https://github.com/progit/progit2-nl) | | Polski | [progit2-pl/progit2-pl](https://github.com/progit2-pl/progit2-pl) | -| Português (Brasil) | [progit2-pt-br/progit2](https://github.com/progit2-pt-br/progit2) | +| Português (Brasil) | [progit/progit2-pt-br](https://github.com/progit/progit2-pt-br) | | Русский | [progit/progit2-ru](https://github.com/progit/progit2-ru) | | Slovenščina | [progit/progit2-sl](https://github.com/progit/progit2-sl) | | Српски | [progit/progit2-sr](https://github.com/progit/progit2-sr) | +| Svenska | [progit2-sv/progit2](https://github.com/progit2-sv/progit2) | | Tagalog | [progit2-tl/progit2](https://github.com/progit2-tl/progit2) | | Türkçe | [progit/progit2-tr](https://github.com/progit/progit2-tr) | | Українська| [progit/progit2-uk](https://github.com/progit/progit2-uk) | @@ -57,8 +58,8 @@ If there is no project for your language, you can start your own translation. Base your work on the second edition of the book, available [here](https://github.com/progit/progit2). To do so: 1. Pick the correct [ISO 639 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language. - 1. Create a [GitHub organization](https://help.github.com/articles/creating-a-new-organization-from-scratch/), for example: `progit2-[your code]` on GitHub. - 1. Create a project ``progit2``. + 1. Create a [GitHub organization](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch), for example: `progit2-[your code]` on GitHub. + 1. Create a project `progit2`. 1. Copy the structure of progit/progit2 (this project) in your project and start translating. ### Updating the status of your translation @@ -71,22 +72,13 @@ On https://git-scm.com, the translations are divided into three categories. Once | Partial translations available in | up to chapter 6 has been translated. | | Full translation available in |the book is (almost) fully translated. | -## Continuous integration with Travis CI +## Continuous integration with GitHub Actions -Travis CI is a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) service that integrates with GitHub. Travis CI is used to ensure that a pull-request doesn't break the build or compilation. Travis CI can also provide compiled versions of the book. +GitHub Actions is a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) service that integrates with GitHub. GitHub Actions is used to ensure that a pull-request doesn't break the build or compilation. GitHub Actions can also provide compiled versions of the book. -Setting up Travis CI requires administrative control over the repository. - -### Registering for Travis continuous integration - -1. Register a Travis account [here](https://travis-ci.org/). -1. Register your project in Travis. -Please refer to the [Travis documentation](https://docs.travis-ci.com/) for more information. - -### Setting up your repository for continuous integration - -Travis CI works by scanning your project's root directory for a file named `.travis.yml` and following the 'recipe' that it contains. The good news is: there's already a working `.travis.yml` file in the Pro Git 2 source [here](https://raw.githubusercontent.com/progit/progit2-pub/master/travis.yml). -Copy that file, and put it in your working directory. Commit the .yml file and push it to your translation repository; that should fire up a compilation and a check of the book's contents. +The configuration for GitHub Actions is contained in the `.github/workflows` directory, and if you bring in the `main` branch of the root repository you'll get them for free. +However, if you created your translation repo by _forking_ the root repo, there's an extra step you must complete (if you did not fork, you can skip this part). +GitHub assumes that forks will be used to contribute to the repo from which they were forked, so you'll have to visit the "Actions" tab on your forked repo, and click the "I understand my workflows" button to allow the actions to run. ## Setting up a publication chain for e-books @@ -96,10 +88,10 @@ This is a technical task, please ping @jnavila to get started with epub publicat Translating the book is the first step. Once this is finished, you could consider translating the user interface of Git itself. -This task requires a more technical knowledge of the tool than the book. Hopefully, after having translated the full book content, you can understand the terms used in the application. If you feel technically up to the task, the repo is [here](https://github.com/git-l10n/git-po) and you just have to follow the [guide](https://github.com/git-l10n/git-po/blob/master/po/README). +This task requires a more technical knowledge of the tool than the book. Hopefully, after having translated the full book content, you can understand the terms used in the application. If you feel technically up to the task, the repo is [here](https://github.com/git-l10n/git-po) and you just have to follow the [guide](https://github.com/git-l10n/git-po/blob/master/po/README.md). Beware though that - * you'll need to use more specific tools to manage localization po files (such as editing them with [poedit](https://poedit.net/) and merging them. You might need to compile git in order to check your work. + * you'll need to use more specific tools to manage localization po files (such as editing them with [poedit](https://poedit.net/)) and merging them. You might need to compile git in order to check your work. * a basic knowledge of how translating applications works is required, which is significantly different from translating books. * the core Git project uses more stringent [procedures](https://github.com/git-l10n/git-po/blob/master/Documentation/SubmittingPatches) to accept contributions, be sure to abide by them. diff --git a/atlas.json b/atlas.json index d66a60a3c..b75c8d65c 100644 --- a/atlas.json +++ b/atlas.json @@ -1,5 +1,5 @@ { - "branch": "master", + "branch": "main", "files": [ "book/cover.html", "LICENSE.asc", diff --git a/book/01-introduction/sections/about-version-control.asc b/book/01-introduction/sections/about-version-control.asc index c76cf1506..182fcedc0 100644 --- a/book/01-introduction/sections/about-version-control.asc +++ b/book/01-introduction/sections/about-version-control.asc @@ -1,7 +1,7 @@ === About Version Control (((version control))) -What is ``version control'', and why should you care? +What is "`version control`", and why should you care? Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. For the examples in this book, you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer. @@ -19,21 +19,21 @@ It is easy to forget which directory you're in and accidentally write to the wro To deal with this issue, programmers long ago developed local VCSs that had a simple database that kept all the changes to files under revision control. -.Local version control. +.Local version control diagram image::images/local.png[Local version control diagram] One of the most popular VCS tools was a system called RCS, which is still distributed with many computers today. -RCS works by keeping patch sets (that is, the differences between files) in a special format on disk; it can then re-create what any file looked like at any point in time by adding up all the patches. +https://www.gnu.org/software/rcs/[RCS^] works by keeping patch sets (that is, the differences between files) in a special format on disk; it can then re-create what any file looked like at any point in time by adding up all the patches. ==== Centralized Version Control Systems (((version control,centralized))) The next major issue that people encounter is that they need to collaborate with developers on other systems. To deal with this problem, Centralized Version Control Systems (CVCSs) were developed. -These systems (such as CVS, Subversion, and Perforce) have a single server that contains all the versioned files, and a number of clients that check out files from that central place. (((CVS)))(((Subversion)))(((Perforce))) +These systems (such as CVS, Subversion, and Perforce) have a single server that contains all the versioned files, and a number of clients that check out files from that central place.(((CVS)))(((Subversion)))(((Perforce))) For many years, this has been the standard for version control. -.Centralized version control. +.Centralized version control diagram image::images/centralized.png[Centralized version control diagram] This setup offers many advantages, especially over local VCSs. @@ -44,17 +44,17 @@ However, this setup also has some serious downsides. The most obvious is the single point of failure that the centralized server represents. If that server goes down for an hour, then during that hour nobody can collaborate at all or save versioned changes to anything they're working on. If the hard disk the central database is on becomes corrupted, and proper backups haven't been kept, you lose absolutely everything -- the entire history of the project except whatever single snapshots people happen to have on their local machines. -Local VCS systems suffer from this same problem -- whenever you have the entire history of the project in a single place, you risk losing everything. +Local VCSs suffer from this same problem -- whenever you have the entire history of the project in a single place, you risk losing everything. ==== Distributed Version Control Systems (((version control,distributed))) This is where Distributed Version Control Systems (DVCSs) step in. -In a DVCS (such as Git, Mercurial, Bazaar or Darcs), clients don't just check out the latest snapshot of the files; rather, they fully mirror the repository, including its full history. +In a DVCS (such as Git, Mercurial or Darcs), clients don't just check out the latest snapshot of the files; rather, they fully mirror the repository, including its full history. Thus, if any server dies, and these systems were collaborating via that server, any of the client repositories can be copied back up to the server to restore it. Every clone is really a full backup of all the data. -.Distributed version control. +.Distributed version control diagram image::images/distributed.png[Distributed version control diagram] Furthermore, many of these systems deal pretty well with having several remote repositories they can work with, so you can collaborate with different groups of people in different ways simultaneously within the same project. diff --git a/book/01-introduction/sections/first-time-setup.asc b/book/01-introduction/sections/first-time-setup.asc index 76949f2be..10b7049ce 100644 --- a/book/01-introduction/sections/first-time-setup.asc +++ b/book/01-introduction/sections/first-time-setup.asc @@ -8,21 +8,20 @@ You can also change them at any time by running through the commands again. Git comes with a tool called `git config` that lets you get and set configuration variables that control all aspects of how Git looks and operates.(((git commands, config))) These variables can be stored in three different places: -1. `/etc/gitconfig` file: Contains values applied to every user on the system and all their repositories. +1. `[path]/etc/gitconfig` file: Contains values applied to every user on the system and all their repositories. If you pass the option `--system` to `git config`, it reads and writes from this file specifically. - (Because this is a system configuration file, you would need administrative or superuser privilege to make changes to it.) + Because this is a system configuration file, you would need administrative or superuser privilege to make changes to it. 2. `~/.gitconfig` or `~/.config/git/config` file: Values specific personally to you, the user. You can make Git read and write to this file specifically by passing the `--global` option, and this affects _all_ of the repositories you work with on your system. 3. `config` file in the Git directory (that is, `.git/config`) of whatever repository you're currently using: Specific to that single repository. You can force Git to read from and write to this file with the `--local` option, but that is in fact the default. - (Unsurprisingly, you need to be located somewhere in a Git repository for this option to work properly.) + Unsurprisingly, you need to be located somewhere in a Git repository for this option to work properly. -Each level overrides values in the previous level, so values in `.git/config` trump those in `/etc/gitconfig`. +Each level overrides values in the previous level, so values in `.git/config` trump those in `[path]/etc/gitconfig`. On Windows systems, Git looks for the `.gitconfig` file in the `$HOME` directory (`C:\Users\$USER` for most people). -It also still looks for `/etc/gitconfig`, although it's relative to the MSys root, which is wherever you decide to install Git on your Windows system when you run the installer. -If you are using version 2.x or later of Git for Windows, there is also a system-level config file at -`C:\Documents and Settings\All Users\Application Data\Git\config` on Windows XP, and in `C:\ProgramData\Git\config` on Windows Vista and newer. +It also still looks for `[path]/etc/gitconfig`, although it's relative to the MSys root, which is wherever you decide to install Git on your Windows system when you run the installer. +If you are using version 2.x or later of Git for Windows, there is also a system-level config file at `C:\Documents and Settings\All Users\Application Data\Git\config` on Windows XP, and in `C:\ProgramData\Git\config` on Windows Vista and newer. This config file can only be changed by `git config -f ` as an admin. You can view all of your settings and where they are coming from using: @@ -43,11 +42,12 @@ $ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com ---- -Again, you need to do this only once if you pass the `--global` option, because then Git will always use that information for anything you do on that system. +Again, you need to do this only once if you pass the `--global` option, because then Git will always use that information for your user on that system. If you want to override this with a different name or email address for specific projects, you can run the command without the `--global` option when you're in that project. Many of the GUI tools will help you do this when you first run them. +[[_editor]] ==== Your Editor Now that your identity is set up, you can configure the default text editor that will be used when Git needs you to type in a message. @@ -68,20 +68,13 @@ If you are on a 32-bit Windows system, or you have a 64-bit editor on a 64-bit s [source,console] ---- -$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -nosession" ----- - -If you have a 32-bit editor on a 64-bit system, the program will be installed in `C:\Program Files (x86)`: - -[source,console] ----- -$ git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -nosession" +$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" ---- [NOTE] ==== Vim, Emacs and Notepad++ are popular text editors often used by developers on Unix-based systems like Linux and macOS or a Windows system. -If you are not familiar with these editors, you may need to search for specific instructions for how to set up your favorite editor with Git. +If you are using another editor, or a 32-bit version, please find specific instructions for how to set up your favorite editor with Git in <>. ==== [WARNING] @@ -90,6 +83,19 @@ You may find, if you don't setup your editor like this, you get into a really co An example on a Windows system may include a prematurely terminated Git operation during a Git initiated edit. ==== +[[_new_default_branch]] +==== Your default branch name + +By default Git will create a branch called _master_ when you create a new repository with `git init`. +From Git version 2.28 onwards, you can set a different name for the initial branch. + +To set _main_ as the default branch name do: + +[source,console] +---- +$ git config --global init.defaultBranch main +---- + ==== Checking Your Settings If you want to check your configuration settings, you can use the `git config --list` command to list all the settings Git can find at that point: @@ -106,7 +112,7 @@ color.diff=auto ... ---- -You may see keys more than once, because Git reads the same key from different files (`/etc/gitconfig` and `~/.gitconfig`, for example). +You may see keys more than once, because Git reads the same key from different files (`[path]/etc/gitconfig` and `~/.gitconfig`, for example). In this case, Git uses the last value for each unique key it sees. You can also check what Git thinks a specific key's value is by typing `git config `:(((git commands, config))) diff --git a/book/01-introduction/sections/help.asc b/book/01-introduction/sections/help.asc index b8a4f8968..68d76a4cf 100644 --- a/book/01-introduction/sections/help.asc +++ b/book/01-introduction/sections/help.asc @@ -1,15 +1,16 @@ [[_git_help]] === Getting Help -If you ever need help while using Git, there are two equivalent ways to get the comprehensive manual page (manpage) help for any of the Git commands: +If you ever need help while using Git, there are three equivalent ways to get the comprehensive manual page (manpage) help for any of the Git commands: [source,console] ---- $ git help +$ git --help $ man git- ---- -For example, you can get the manpage help for the `git config` command by running(((git commands, help))) +For example, you can get the manpage help for the `git config` command by running this:(((git commands, help))) [source,console] ---- @@ -17,31 +18,33 @@ $ git help config ---- These commands are nice because you can access them anywhere, even offline. -If the manpages and this book aren't enough and you need in-person help, you can try the `#git` or `#github` channel on the Freenode IRC server, which can be found at https://freenode.net[]. +If the manpages and this book aren't enough and you need in-person help, you can try the `#git`, `#github`, or `#gitlab` channels on the Libera Chat IRC server, which can be found at https://libera.chat/[^]. These channels are regularly filled with hundreds of people who are all very knowledgeable about Git and are often willing to help.(((IRC))) -In addition, if you don't need the full-blown manpage help, but just need a quick refresher on the available options for a Git command, you can ask for the more concise ``help'' output with the `-h` or `--help` options, as in: +In addition, if you don't need the full-blown manpage help, but just need a quick refresher on the available options for a Git command, you can ask for the more concise "`help`" output with the `-h` option, as in: [source,console] ---- $ git add -h usage: git add [] [--] ... - -n, --dry-run dry run - -v, --verbose be verbose - - -i, --interactive interactive picking - -p, --patch select hunks interactively - -e, --edit edit current diff and apply - -f, --force allow adding otherwise ignored files - -u, --update update tracked files - --renormalize renormalize EOL of tracked files (implies -u) - -N, --intent-to-add record only the fact that the path will be added later - -A, --all add changes from all tracked and untracked files - --ignore-removal ignore paths removed in the working tree (same as --no-all) - --refresh don't add, only refresh the index - --ignore-errors just skip files which cannot be added because of errors - --ignore-missing check if - even missing - files are ignored in dry run - --chmod (+|-)x override the executable bit of the listed files + -n, --dry-run dry run + -v, --verbose be verbose + + -i, --interactive interactive picking + -p, --patch select hunks interactively + -e, --edit edit current diff and apply + -f, --force allow adding otherwise ignored files + -u, --update update tracked files + --renormalize renormalize EOL of tracked files (implies -u) + -N, --intent-to-add record only the fact that the path will be added later + -A, --all add changes from all tracked and untracked files + --ignore-removal ignore paths removed in the working tree (same as --no-all) + --refresh don't add, only refresh the index + --ignore-errors just skip files which cannot be added because of errors + --ignore-missing check if - even missing - files are ignored in dry run + --sparse allow updating entries outside of the sparse-checkout cone + --chmod (+|-)x override the executable bit of the listed files + --pathspec-from-file read pathspec from file + --pathspec-file-nul with --pathspec-from-file, pathspec elements are separated with NUL character ---- - diff --git a/book/01-introduction/sections/history.asc b/book/01-introduction/sections/history.asc index dd1d096f9..7ab05fd3b 100644 --- a/book/01-introduction/sections/history.asc +++ b/book/01-introduction/sections/history.asc @@ -3,18 +3,18 @@ As with many great things in life, Git began with a bit of creative destruction and fiery controversy. The Linux kernel is an open source software project of fairly large scope.(((Linux))) -For most of the lifetime of the Linux kernel maintenance (1991–2002), changes to the software were passed around as patches and archived files. +During the early years of the Linux kernel maintenance (1991–2002), changes to the software were passed around as patches and archived files. In 2002, the Linux kernel project began using a proprietary DVCS called BitKeeper.(((BitKeeper))) In 2005, the relationship between the community that developed the Linux kernel and the commercial company that developed BitKeeper broke down, and the tool's free-of-charge status was revoked. This prompted the Linux development community (and in particular Linus Torvalds, the creator of Linux) to develop their own tool based on some of the lessons they learned while using BitKeeper.(((Linus Torvalds))) Some of the goals of the new system were as follows: -* Speed -* Simple design -* Strong support for non-linear development (thousands of parallel branches) -* Fully distributed -* Able to handle large projects like the Linux kernel efficiently (speed and data size) +* Speed +* Simple design +* Strong support for non-linear development (thousands of parallel branches) +* Fully distributed +* Able to handle large projects like the Linux kernel efficiently (speed and data size) Since its birth in 2005, Git has evolved and matured to be easy to use and yet retain these initial qualities. -It's amazingly fast, it's very efficient with large projects, and it has an incredible branching system for non-linear development (See <>). +It's amazingly fast, it's very efficient with large projects, and it has an incredible branching system for non-linear development (see <>). diff --git a/book/01-introduction/sections/installing.asc b/book/01-introduction/sections/installing.asc index 29dbd7010..d4f6dcbd1 100644 --- a/book/01-introduction/sections/installing.asc +++ b/book/01-introduction/sections/installing.asc @@ -6,9 +6,9 @@ You can either install it as a package or via another installer, or download the [NOTE] ==== -This book was written using Git version *2.8.0*. -Though most of the commands we use should work even in ancient versions of Git, some of them might not or might act slightly differently if you're using an older version. -Since Git is quite excellent at preserving backwards compatibility, any version after 2.0 should work just fine. +This book was written using Git version 2. +Since Git is quite excellent at preserving backwards compatibility, any recent version should work just fine. +Though most of the commands we use should work even in ancient versions of Git, some of them might not or might act slightly differently. ==== ==== Installing on Linux @@ -29,14 +29,14 @@ If you're on a Debian-based distribution, such as Ubuntu, try `apt`: $ sudo apt install git-all ---- -For more options, there are instructions for installing on several different Unix distributions on the Git website, at https://git-scm.com/download/linux[]. +For more options, there are instructions for installing on several different Unix distributions on the Git website, at https://git-scm.com/download/linux[^]. ==== Installing on macOS (((macOS, installing))) -There are several ways to install Git on a Mac. +There are several ways to install Git on macOS. The easiest is probably to install the Xcode Command Line Tools.(((Xcode))) -On Mavericks (10.9) or above you can do this simply by trying to run 'git' from the Terminal the very first time. +On Mavericks (10.9) or above you can do this simply by trying to run `git` from the Terminal the very first time. [source,console] ---- @@ -46,31 +46,21 @@ $ git --version If you don't have it installed already, it will prompt you to install it. If you want a more up to date version, you can also install it via a binary installer. -A macOS Git installer is maintained and available for download at the Git website, at https://git-scm.com/download/mac[]. +A macOS Git installer is maintained and available for download at the Git website, at https://git-scm.com/download/mac[^]. -.Git macOS Installer. -image::images/git-osx-installer.png[Git macOS installer.] - -You can also install it as part of the GitHub for macOS install. -Their GUI Git tool has an option to install command line tools as well. -You can download that tool from the GitHub for macOS website, at https://desktop.github.com[]. +.Git macOS installer +image::images/git-osx-installer.png[Git macOS installer] ==== Installing on Windows There are also a few ways to install Git on Windows.(((Windows, installing))) The most official build is available for download on the Git website. -Just go to https://git-scm.com/download/win[] and the download will start automatically. -Note that this is a project called Git for Windows, which is separate from Git itself; for more information on it, go to https://gitforwindows.org[]. +Just go to https://git-scm.com/download/win[^] and the download will start automatically. +Note that this is a project called Git for Windows, which is separate from Git itself; for more information on it, go to https://gitforwindows.org[^]. -To get an automated installation you can use the https://chocolatey.org/packages/git[Git Chocolatey package]. +To get an automated installation you can use the https://community.chocolatey.org/packages/git[Git Chocolatey package^]. Note that the Chocolatey package is community maintained. -Another easy way to get Git installed is by installing GitHub Desktop. -The installer includes a command line version of Git as well as the GUI. -It also works well with PowerShell, and sets up solid credential caching and sane CRLF settings.(((PowerShell)))(((CRLF)))(((credential caching))) -We'll learn more about those things a little later, but suffice it to say they're things you want. -You can download this from the https://desktop.github.com[GitHub Desktop website]. - ==== Installing from Source Some people may instead find it useful to install Git from source, because you'll get the most recent version. @@ -87,7 +77,7 @@ $ sudo apt-get install dh-autoreconf libcurl4-gnutls-dev libexpat1-dev \ gettext libz-dev libssl-dev ---- -In order to be able to add the documentation in various formats (doc, html, info), these additional dependencies are required (Note: users of RHEL and RHEL-derivatives like CentOS and Scientific Linux will have to https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F[enable the EPEL repository] to download the `docbook2X` package): +In order to be able to add the documentation in various formats (doc, html, info), these additional dependencies are required: [source,console] ---- @@ -95,6 +85,11 @@ $ sudo dnf install asciidoc xmlto docbook2X $ sudo apt-get install asciidoc xmlto docbook2x ---- +[NOTE] +==== +Users of RHEL and RHEL-derivatives like CentOS and Scientific Linux will have to https://docs.fedoraproject.org/en-US/epel/#how_can_i_use_these_extra_packages[enable the EPEL repository^] to download the `docbook2X` package. +==== + If you're using a Debian-based distribution (Debian/Ubuntu/Ubuntu-derivatives), you also need the `install-info` package: [source,console] @@ -107,10 +102,9 @@ If you're using a RPM-based distribution (Fedora/RHEL/RHEL-derivatives), you als [source,console] ---- $ sudo dnf install getopt -$ sudo apt-get install getopt ---- -Additionally, if you're using Fedora/RHEL/RHEL-derivatives, you need to do this +Additionally, if you're using Fedora/RHEL/RHEL-derivatives, you need to do this: [source,console] ---- @@ -120,15 +114,15 @@ $ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi due to binary name differences. When you have all the necessary dependencies, you can go ahead and grab the latest tagged release tarball from several places. -You can get it via the kernel.org site, at https://www.kernel.org/pub/software/scm/git[], or the mirror on the GitHub website, at https://github.com/git/git/releases[]. +You can get it via the kernel.org site, at https://www.kernel.org/pub/software/scm/git[^], or the mirror on the GitHub website, at https://github.com/git/git/tags[^]. It's generally a little clearer what the latest version is on the GitHub page, but the kernel.org page also has release signatures if you want to verify your download. Then, compile and install: [source,console] ---- -$ tar -zxf git-2.0.0.tar.gz -$ cd git-2.0.0 +$ tar -zxf git-2.8.0.tar.gz +$ cd git-2.8.0 $ make configure $ ./configure --prefix=/usr $ make all doc info @@ -139,5 +133,5 @@ After this is done, you can also get Git via Git itself for updates: [source,console] ---- -$ git clone git://git.kernel.org/pub/scm/git/git.git +$ git clone https://git.kernel.org/pub/scm/git/git.git ---- diff --git a/book/01-introduction/sections/what-is-git.asc b/book/01-introduction/sections/what-is-git.asc index 827e4be1f..466201b23 100644 --- a/book/01-introduction/sections/what-is-git.asc +++ b/book/01-introduction/sections/what-is-git.asc @@ -1,3 +1,4 @@ +[[what_is_git_section]] === What is Git? So, what is Git in a nutshell? @@ -9,10 +10,10 @@ Even though Git's user interface is fairly similar to these other VCSs, Git stor The major difference between Git and any other VCS (Subversion and friends included) is the way Git thinks about its data. Conceptually, most other systems store information as a list of file-based changes. -These other systems (CVS, Subversion, Perforce, Bazaar, and so on) think of the information they store as a set of files and the changes made to each file over time (this is commonly described as _delta-based_ version control). +These other systems (CVS, Subversion, Perforce, and so on) think of the information they store as a set of files and the changes made to each file over time (this is commonly described as _delta-based_ version control). -.Storing data as changes to a base version of each file. -image::images/deltas.png[Storing data as changes to a base version of each file.] +.Storing data as changes to a base version of each file +image::images/deltas.png[Storing data as changes to a base version of each file] Git doesn't think of or store its data this way. Instead, Git thinks of its data more like a series of snapshots of a miniature filesystem. @@ -20,8 +21,8 @@ With Git, every time you commit, or save the state of your project, Git basicall To be efficient, if files have not changed, Git doesn't store the file again, just a link to the previous identical file it has already stored. Git thinks about its data more like a *stream of snapshots*. -.Storing data as snapshots of the project over time. -image::images/snapshots.png[Git stores data as snapshots of the project over time.] +.Storing data as snapshots of the project over time +image::images/snapshots.png[Git stores data as snapshots of the project over time] This is an important distinction between Git and nearly all other VCSs. It makes Git reconsider almost every aspect of version control that most other systems copied from the previous generation. @@ -76,25 +77,25 @@ For a more in-depth look at how Git stores its data and how you can recover data ==== The Three States Pay attention now -- here is the main thing to remember about Git if you want the rest of your learning process to go smoothly. -Git has three main states that your files can reside in: _committed_, _modified_, and _staged_: +Git has three main states that your files can reside in: _modified_, _staged_, and _committed_: -* Committed means that the data is safely stored in your local database. * Modified means that you have changed the file but have not committed it to your database yet. * Staged means that you have marked a modified file in its current version to go into your next commit snapshot. +* Committed means that the data is safely stored in your local database. -This leads us to the three main sections of a Git project: the Git directory, the working tree, and the staging area. - -.Working tree, staging area, and Git directory. -image::images/areas.png["Working tree, staging area, and Git directory."] +This leads us to the three main sections of a Git project: the working tree, the staging area, and the Git directory. -The Git directory is where Git stores the metadata and object database for your project. -This is the most important part of Git, and it is what is copied when you _clone_ a repository from another computer. +.Working tree, staging area, and Git directory +image::images/areas.png["Working tree, staging area, and Git directory"] The working tree is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify. The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. -Its technical name in Git parlance is the ``index'', but the phrase ``staging area'' works just as well. +Its technical name in Git parlance is the "`index`", but the phrase "`staging area`" works just as well. + +The Git directory is where Git stores the metadata and object database for your project. +This is the most important part of Git, and it is what is copied when you _clone_ a repository from another computer. The basic Git workflow goes something like this: diff --git a/book/02-git-basics/sections/aliases.asc b/book/02-git-basics/sections/aliases.asc index 2c9c7c020..5d6d117cd 100644 --- a/book/02-git-basics/sections/aliases.asc +++ b/book/02-git-basics/sections/aliases.asc @@ -2,8 +2,8 @@ === Git Aliases (((aliases))) -Before we finish this chapter on basic Git, there's just one little tip that can make your Git experience simpler, easier, and more familiar: aliases. -We won't refer to them or assume you've used them later in the book, but you should probably know how to use them. +Before we move on to the next chapter, we want to introduce a feature that can make your Git experience simpler, easier, and more familiar: aliases. +For clarity's sake, we won't be using them anywhere else in this book, but if you go on to use Git with any regularity, aliases are something you should know about. Git doesn't automatically infer your command if you type it in partially. If you don't want to type the entire text of each of the Git commands, you can easily set up an alias for each command using `git config`.(((git commands, config))) @@ -53,7 +53,7 @@ commit 66938dae3329c7aebe598c2246a8e6af90d04646 Author: Josh Goebel Date: Tue Aug 26 19:48:51 2008 +0800 - test for current head + Test for current head Signed-off-by: Scott Chacon ---- diff --git a/book/02-git-basics/sections/getting-a-repository.asc b/book/02-git-basics/sections/getting-a-repository.asc index ea7a21cab..3b69efd08 100644 --- a/book/02-git-basics/sections/getting-a-repository.asc +++ b/book/02-git-basics/sections/getting-a-repository.asc @@ -26,7 +26,7 @@ $ cd /Users/user/my_project for Windows: [source,console] ---- -$ cd /c/user/my_project +$ cd C:/Users/user/my_project ---- and type: @@ -38,7 +38,7 @@ $ git init This creates a new subdirectory named `.git` that contains all of your necessary repository files -- a Git repository skeleton. At this point, nothing in your project is tracked yet. -(See <> for more information about exactly what files are contained in the `.git` directory you just created.)(((git commands, init))) +See <> for more information about exactly what files are contained in the `.git` directory you just created.(((git commands, init))) If you want to start version-controlling existing files (as opposed to an empty directory), you should probably begin tracking those files and do an initial commit. You can accomplish that with a few `git add` commands that specify the files you want to track, followed by a `git commit`: @@ -47,7 +47,7 @@ You can accomplish that with a few `git add` commands that specify the files you ---- $ git add *.c $ git add LICENSE -$ git commit -m 'initial project version' +$ git commit -m 'Initial project version' ---- We'll go over what these commands do in just a minute. @@ -57,7 +57,7 @@ At this point, you have a Git repository with tracked files and an initial commi ==== Cloning an Existing Repository If you want to get a copy of an existing Git repository -- for example, a project you'd like to contribute to -- the command you need is `git clone`. -If you're familiar with other VCS systems such as Subversion, you'll notice that the command is "clone" and not "checkout". +If you're familiar with other VCSs such as Subversion, you'll notice that the command is "clone" and not "checkout". This is an important distinction -- instead of getting just a working copy, Git receives a full copy of nearly all data that the server has. Every version of every file for the history of the project is pulled down by default when you run `git clone`. In fact, if your server disk gets corrupted, you can often use nearly any of the clones on any client to set the server back to the state it was in when it was cloned (you may lose some server-side hooks and such, but all the versioned data would be there -- see <> for more details). diff --git a/book/02-git-basics/sections/recording-changes.asc b/book/02-git-basics/sections/recording-changes.asc index e48751fcf..8bcd785fe 100644 --- a/book/02-git-basics/sections/recording-changes.asc +++ b/book/02-git-basics/sections/recording-changes.asc @@ -4,7 +4,7 @@ At this point, you should have a _bona fide_ Git repository on your local machin Typically, you'll want to start making changes and committing snapshots of those changes into your repository each time the project reaches a state you want to record. Remember that each file in your working directory can be in one of two states: _tracked_ or _untracked_. -Tracked files are files that were in the last snapshot; they can be unmodified, modified, or staged. +Tracked files are files that were in the last snapshot, as well as any newly staged files; they can be unmodified, modified, or staged. In short, tracked files are files that Git knows about. Untracked files are everything else -- any files in your working directory that were not in your last snapshot and are not in your staging area. @@ -13,8 +13,8 @@ When you first clone a repository, all of your files will be tracked and unmodif As you edit files, Git sees them as modified, because you've changed them since your last commit. As you work, you selectively stage these modified files and then commit all those staged changes, and the cycle repeats. -.The lifecycle of the status of your files. -image::images/lifecycle.png[The lifecycle of the status of your files.] +.The lifecycle of the status of your files +image::images/lifecycle.png[The lifecycle of the status of your files] [[_checking_status]] ==== Checking the Status of Your Files @@ -27,15 +27,24 @@ If you run this command directly after a clone, you should see something like th $ git status On branch master Your branch is up-to-date with 'origin/master'. -nothing to commit, working directory clean +nothing to commit, working tree clean ---- This means you have a clean working directory; in other words, none of your tracked files are modified. Git also doesn't see any untracked files, or they would be listed here. Finally, the command tells you which branch you're on and informs you that it has not diverged from the same branch on the server. -For now, that branch is always ``master'', which is the default; you won't worry about it here. +For now, that branch is always `master`, which is the default; you won't worry about it here. <> will go over branches and references in detail. +[NOTE] +==== +GitHub changed the default branch name from `master` to `main` in mid-2020, and other Git hosts followed suit. +So you may find that the default branch name in some newly created repositories is `main` and not `master`. +In addition, the default branch name can be changed (as you have seen in <>), so you may see a different name for the default branch. + +However, Git itself still uses `master` as the default, so we will use it throughout the book. +==== + Let's say you add a new file to your project, a simple `README` file. If the file didn't exist before, and you run `git status`, you see your untracked file like so: @@ -53,8 +62,8 @@ Untracked files: nothing added to commit but untracked files present (use "git add" to track) ---- -You can see that your new `README` file is untracked, because it's under the ``Untracked files'' heading in your status output. -Untracked basically means that Git sees a file you didn't have in the previous snapshot (commit); Git won't start including it in your commit snapshots until you explicitly tell it to do so. +You can see that your new `README` file is untracked, because it's under the "`Untracked files`" heading in your status output. +Untracked basically means that Git sees a file you didn't have in the previous snapshot (commit), and which hasn't yet been staged; Git won't start including it in your commit snapshots until you explicitly tell it to do so. It does this so you don't accidentally begin including generated binary files or other files that you did not mean to include. You do want to start including `README`, so let's start tracking the file. @@ -77,13 +86,13 @@ $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: - (use "git reset HEAD ..." to unstage) + (use "git restore --staged ..." to unstage) new file: README ---- -You can tell that it's staged because it's under the ``Changes to be committed'' heading. +You can tell that it's staged because it's under the "`Changes to be committed`" heading. If you commit at this point, the version of the file at the time you ran `git add` is what will be in the subsequent historical snapshot. You may recall that when you ran `git init` earlier, you then ran `git add ` -- that was to begin tracking files in your directory.(((git commands, init)))(((git commands, add))) The `git add` command takes a path name for either a file or a directory; if it's a directory, the command adds all the files in that directory recursively. @@ -111,10 +120,10 @@ Changes not staged for commit: ---- -The `CONTRIBUTING.md` file appears under a section named ``Changes not staged for commit'' -- which means that a file that is tracked has been modified in the working directory but not yet staged. +The `CONTRIBUTING.md` file appears under a section named "`Changes not staged for commit`" -- which means that a file that is tracked has been modified in the working directory but not yet staged. To stage it, you run the `git add` command. `git add` is a multipurpose command -- you use it to begin tracking new files, to stage files, and to do other things like marking merge-conflicted files as resolved. -It may be helpful to think of it more as ``add precisely this content to the next commit'' rather than ``add this file to the project''.(((git commands, add))) +It may be helpful to think of it more as "`add precisely this content to the next commit`" rather than "`add this file to the project`".(((git commands, add))) Let's run `git add` now to stage the `CONTRIBUTING.md` file, and then run `git status` again: [source,console] @@ -212,21 +221,21 @@ $ cat .gitignore *~ ---- -The first line tells Git to ignore any files ending in ``.o'' or ``.a'' -- object and archive files that may be the product of building your code. +The first line tells Git to ignore any files ending in "`.o`" or "`.a`" -- object and archive files that may be the product of building your code. The second line tells Git to ignore all files whose names end with a tilde (`~`), which is used by many text editors such as Emacs to mark temporary files. You may also include a log, tmp, or pid directory; automatically generated documentation; and so on. Setting up a `.gitignore` file for your new repository before you get going is generally a good idea so you don't accidentally commit files that you really don't want in your Git repository. The rules for the patterns you can put in the `.gitignore` file are as follows: -* Blank lines or lines starting with `#` are ignored. -* Standard glob patterns work, and will be applied recursively throughout the entire working tree. -* You can start patterns with a forward slash (`/`) to avoid recursivity. -* You can end patterns with a forward slash (`/`) to specify a directory. -* You can negate a pattern by starting it with an exclamation point (`!`). +* Blank lines or lines starting with `#` are ignored. +* Standard glob patterns work, and will be applied recursively throughout the entire working tree. +* You can start patterns with a forward slash (`/`) to avoid recursivity. +* You can end patterns with a forward slash (`/`) to specify a directory. +* You can negate a pattern by starting it with an exclamation point (`!`). Glob patterns are like simplified regular expressions that shells use. -An asterisk (`*`) matches zero or more characters; `[abc]` matches any character inside the brackets (in this case a, b, or c); a question mark (`?`) matches a single character; and brackets enclosing characters separated by a hyphen (`[0-9]`) matches any character between them (in this case 0 through 9). +An asterisk (`\*`) matches zero or more characters; `[abc]` matches any character inside the brackets (in this case a, b, or c); a question mark (`?`) matches a single character; and brackets enclosing characters separated by a hyphen (`[0-9]`) matches any character between them (in this case 0 through 9). You can also use two asterisks to match nested directories; `a/**/z` would match `a/z`, `a/b/z`, `a/b/c/z`, and so on. Here is another example `.gitignore` file: @@ -254,7 +263,7 @@ doc/**/*.pdf [TIP] ==== -GitHub maintains a fairly comprehensive list of good `.gitignore` file examples for dozens of projects and languages at https://github.com/github/gitignore[] if you want a starting point for your project. +GitHub maintains a fairly comprehensive list of good `.gitignore` file examples for dozens of projects and languages at https://github.com/github/gitignore[^] if you want a starting point for your project. ==== [NOTE] @@ -262,7 +271,7 @@ GitHub maintains a fairly comprehensive list of good `.gitignore` file examples In the simple case, a repository might have a single `.gitignore` file in its root directory, which applies recursively to the entire repository. However, it is also possible to have additional `.gitignore` files in subdirectories. The rules in these nested `.gitignore` files apply only to the files under the directory where they are located. -(The Linux kernel source repository has 206 `.gitignore` files.) +The Linux kernel source repository has 206 `.gitignore` files. It is beyond the scope of this book to get into the details of multiple `.gitignore` files; see `man gitignore` for the details. ==== @@ -420,7 +429,11 @@ $ git commit ---- Doing so launches your editor of choice. -(This is set by your shell's `EDITOR` environment variable -- usually vim or emacs, although you can configure it with whatever you want using the `git config --global core.editor` command as you saw in <>).(((editor, changing default)))(((git commands, config))) + +[NOTE] +==== +This is set by your shell's `EDITOR` environment variable -- usually vim or emacs, although you can configure it with whatever you want using the `git config --global core.editor` command as you saw in <>.(((editor, changing default)))(((git commands, config))) +==== The editor displays the following text (this example is a Vim screen): @@ -444,16 +457,21 @@ The editor displays the following text (this example is a Vim screen): You can see that the default commit message contains the latest output of the `git status` command commented out and one empty line on top. You can remove these comments and type your commit message, or you can leave them there to help you remember what you're committing. -(For an even more explicit reminder of what you've modified, you can pass the `-v` option to `git commit`. -Doing so also puts the diff of your change in the editor so you can see exactly what changes you're committing.) + +[NOTE] +==== +For an even more explicit reminder of what you've modified, you can pass the `-v` option to `git commit`. +Doing so also puts the diff of your change in the editor so you can see exactly what changes you're committing. +==== + When you exit the editor, Git creates your commit with that commit message (with the comments and diff stripped out). Alternatively, you can type your commit message inline with the `commit` command by specifying it after a `-m` flag, like this: [source,console] ---- -$ git commit -m "Story 182: Fix benchmarks for speed" -[master 463dc4f] Story 182: Fix benchmarks for speed +$ git commit -m "Story 182: fix benchmarks for speed" +[master 463dc4f] Story 182: fix benchmarks for speed 2 files changed, 2 insertions(+) create mode 100644 README ---- @@ -484,8 +502,8 @@ Changes not staged for commit: modified: CONTRIBUTING.md no changes added to commit (use "git add" and/or "git commit -a") -$ git commit -a -m 'added new benchmarks' -[master 83e38c7] added new benchmarks +$ git commit -a -m 'Add new benchmarks' +[master 83e38c7] Add new benchmarks 1 file changed, 5 insertions(+), 0 deletions(-) ---- @@ -500,7 +518,7 @@ This is convenient, but be careful; sometimes this flag will cause you to includ To remove a file from Git, you have to remove it from your tracked files (more accurately, remove it from your staging area) and then commit. The `git rm` command does that, and also removes the file from your working directory so you don't see it as an untracked file the next time around. -If you simply remove the file from your working directory, it shows up under the ``Changes not staged for commit'' (that is, _unstaged_) area of your `git status` output: +If you simply remove the file from your working directory, it shows up under the "`Changes not staged for commit`" (that is, _unstaged_) area of your `git status` output: [source,console] ---- @@ -570,7 +588,7 @@ This command removes all files whose names end with a `~`. ==== Moving Files (((files, moving))) -Unlike many other VCS systems, Git doesn't explicitly track file movement. +Unlike many other VCSs, Git doesn't explicitly track file movement. If you rename a file in Git, no metadata is stored in Git that tells it you renamed the file. However, Git is pretty smart about figuring that out after the fact -- we'll deal with detecting file movement a bit later. @@ -608,4 +626,4 @@ $ git add README Git figures out that it's a rename implicitly, so it doesn't matter if you rename a file that way or with the `mv` command. The only real difference is that `git mv` is one command instead of three -- it's a convenience function. -More importantly, you can use any tool you like to rename a file, and address the add/rm later, before you commit. +More importantly, you can use any tool you like to rename a file, and address the `add`/`rm` later, before you commit. diff --git a/book/02-git-basics/sections/remotes.asc b/book/02-git-basics/sections/remotes.asc index a150fbf6b..80e98250a 100644 --- a/book/02-git-basics/sections/remotes.asc +++ b/book/02-git-basics/sections/remotes.asc @@ -11,8 +11,8 @@ In this section, we'll cover some of these remote-management skills. [NOTE] .Remote repositories can be on your local machine. ==== -It is entirely possible that you can be working with a ``remote'' repository that is, in fact, on the same host you are. -The word ``remote'' does not necessarily imply that the repository is somewhere else on the network or Internet, only that it is elsewhere. +It is entirely possible that you can be working with a "`remote`" repository that is, in fact, on the same host you are. +The word "`remote`" does not necessarily imply that the repository is somewhere else on the network or Internet, only that it is elsewhere. Working with such a remote repository would still involve all the standard pushing, pulling and fetching operations as with any other remote. ==== @@ -87,7 +87,7 @@ pb https://github.com/paulboone/ticgit (fetch) pb https://github.com/paulboone/ticgit (push) ---- -Now you can use the string `pb` on the command line in lieu of the whole URL. +Now you can use the string `pb` on the command line instead of the whole URL. For example, if you want to fetch all the information that Paul has but that you don't yet have in your repository, you can run `git fetch pb`: [source,console] @@ -102,8 +102,8 @@ From https://github.com/paulboone/ticgit * [new branch] ticgit -> pb/ticgit ---- -Paul's master branch is now accessible locally as `pb/master` -- you can merge it into one of your branches, or you can check out a local branch at that point if you want to inspect it. -(We'll go over what branches are and how to use them in much more detail in <>.) +Paul's `master` branch is now accessible locally as `pb/master` -- you can merge it into one of your branches, or you can check out a local branch at that point if you want to inspect it. +We'll go over what branches are and how to use them in much more detail in <>. [[_fetching_and_pulling]] ==== Fetching and Pulling from Your Remotes @@ -118,21 +118,33 @@ $ git fetch The command goes out to that remote project and pulls down all the data from that remote project that you don't have yet. After you do this, you should have references to all the branches from that remote, which you can merge in or inspect at any time. -If you clone a repository, the command automatically adds that remote repository under the name ``origin''. +If you clone a repository, the command automatically adds that remote repository under the name "`origin`". So, `git fetch origin` fetches any new work that has been pushed to that server since you cloned (or last fetched from) it. It's important to note that the `git fetch` command only downloads the data to your local repository -- it doesn't automatically merge it with any of your work or modify what you're currently working on. You have to merge it manually into your work when you're ready. If your current branch is set up to track a remote branch (see the next section and <> for more information), you can use the `git pull` command to automatically fetch and then merge that remote branch into your current branch.(((git commands, pull))) -This may be an easier or more comfortable workflow for you; and by default, the `git clone` command automatically sets up your local master branch to track the remote master branch (or whatever the default branch is called) on the server you cloned from. +This may be an easier or more comfortable workflow for you; and by default, the `git clone` command automatically sets up your local `master` branch to track the remote `master` branch (or whatever the default branch is called) on the server you cloned from. Running `git pull` generally fetches data from the server you originally cloned from and automatically tries to merge it into the code you're currently working on. +[NOTE] +==== +From Git version 2.27 onward, `git pull` will give a warning if the `pull.rebase` variable is not set. +Git will keep warning you until you set the variable. + +If you want the default behavior of Git (fast-forward if possible, else create a merge commit): +`git config --global pull.rebase "false"` + +If you want to rebase when pulling: +`git config --global pull.rebase "true"` +==== + [[_pushing_remotes]] ==== Pushing to Your Remotes When you have your project at a point that you want to share, you have to push it upstream. The command for this is simple: `git push `.(((git commands, push))) -If you want to push your master branch to your `origin` server (again, cloning generally sets up both of those names for you automatically), then you can run this to push any commits you've done back up to the server: +If you want to push your `master` branch to your `origin` server (again, cloning generally sets up both of those names for you automatically), then you can run this to push any commits you've done back up to the server: [source,console] ---- @@ -167,7 +179,7 @@ $ git remote show origin ---- It lists the URL for the remote repository as well as the tracking branch information. -The command helpfully tells you that if you're on the master branch and you run `git pull`, it will automatically merge in the master branch on the remote after it fetches all the remote references. +The command helpfully tells you that if you're on the `master` branch and you run `git pull`, it will automatically merge the remote's `master` branch into the local one after it has been fetched. It also lists all the remote references it has pulled down. That is a simple example you're likely to encounter. diff --git a/book/02-git-basics/sections/tagging.asc b/book/02-git-basics/sections/tagging.asc index 0ae6ae7ac..34604c573 100644 --- a/book/02-git-basics/sections/tagging.asc +++ b/book/02-git-basics/sections/tagging.asc @@ -91,7 +91,7 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number + Change version number ---- That shows the tagger information, the date the commit was tagged, and the annotation message before showing the commit information. @@ -124,7 +124,7 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number + Change version number ---- ==== Tagging Later @@ -136,18 +136,18 @@ Suppose your commit history looks like this: ---- $ git log --pretty=oneline 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' -a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support -0d52aaab4479697da7686c15f77a3d64d9165190 one more thing +a6b4c97498bd301d84096da251c98a07c7723e65 Create write support +0d52aaab4479697da7686c15f77a3d64d9165190 One more thing 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' -0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function -4682c3261057305bdd616e23b64b0857d832627b added a todo file -166ae0c4d3f420721acbb115cc33848dfcc2121a started write support -9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile -964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo -8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme +0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc Add commit function +4682c3261057305bdd616e23b64b0857d832627b Add todo file +166ae0c4d3f420721acbb115cc33848dfcc2121a Create write support +9fceb02d0ae598e95dc970b74767f19372d61af8 Update rakefile +964f16d36dfccde844893cac5b347e7b3d44abbc Commit the todo +8a5cbc430f1a9c3d00faaeffd07798508422908a Update readme ---- -Now, suppose you forgot to tag the project at v1.2, which was at the ``updated rakefile'' commit. +Now, suppose you forgot to tag the project at v1.2, which was at the "`Update rakefile`" commit. You can add it after the fact. To tag that commit, you specify the commit checksum (or part of it) at the end of the command: @@ -178,7 +178,7 @@ commit 9fceb02d0ae598e95dc970b74767f19372d61af8 Author: Magnus Chacon Date: Sun Apr 27 20:43:35 2008 -0700 - updated rakefile + Update rakefile ... ---- @@ -220,7 +220,8 @@ Now, when someone else clones or pulls from your repository, they will get all y [NOTE] .`git push` pushes both types of tags ==== -Pushing tags using `git push --tags` does not distinguish between lightweight and annotated tags; there is no simple option that allows you to select just one type for pushing. +`git push --tags` will push both lightweight and annotated tags. +There is currently no option to push only lightweight tags, but if you use `git push --follow-tags` only annotated tags will be pushed to the remote. ==== ==== Deleting Tags @@ -257,30 +258,36 @@ $ git push origin --delete ==== Checking out Tags -If you want to view the versions of files a tag is pointing to, you can do a `git checkout` of that tag, although this puts your repository in ``detached HEAD'' state, which has some ill side effects: +If you want to view the versions of files a tag is pointing to, you can do a `git checkout` of that tag, although this puts your repository in "`detached HEAD`" state, which has some ill side effects: [source,console] ---- -$ git checkout 2.0.0 -Note: checking out '2.0.0'. +$ git checkout v2.0.0 +Note: switching to 'v2.0.0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may -do so (now or later) by using -b with the checkout command again. Example: +do so (now or later) by using -c with the switch command. Example: - git checkout -b + git switch -c + +Or undo this operation with: + + git switch - + +Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 99ada87... Merge pull request #89 from schacon/appendix-final -$ git checkout 2.0-beta-0.1 +$ git checkout v2.0-beta-0.1 Previous HEAD position was 99ada87... Merge pull request #89 from schacon/appendix-final -HEAD is now at df3f601... add atlas.json and cover image +HEAD is now at df3f601... Add atlas.json and cover image ---- -In ``detached HEAD'' state, if you make changes and then create a commit, the tag will stay the same, but your new commit won't belong to any branch and will be unreachable, except by the exact commit hash. +In "`detached HEAD`" state, if you make changes and then create a commit, the tag will stay the same, but your new commit won't belong to any branch and will be unreachable, except by the exact commit hash. Thus, if you need to make changes -- say you're fixing a bug on an older version, for instance -- you will generally want to create a branch: [source,console] diff --git a/book/02-git-basics/sections/undoing.asc b/book/02-git-basics/sections/undoing.asc index a6780602c..0c815dde8 100644 --- a/book/02-git-basics/sections/undoing.asc +++ b/book/02-git-basics/sections/undoing.asc @@ -24,7 +24,7 @@ As an example, if you commit and then realize you forgot to stage the changes in [source,console] ---- -$ git commit -m 'initial commit' +$ git commit -m 'Initial commit' $ git add forgotten_file $ git commit --amend ---- @@ -36,7 +36,14 @@ You end up with a single commit -- the second commit replaces the results of the It's important to understand that when you're amending your last commit, you're not so much fixing it as _replacing_ it entirely with a new, improved commit that pushes the old commit out of the way and puts the new commit in its place. Effectively, it's as if the previous commit never happened, and it won't show up in your repository history. -The obvious value to amending commits is to make minor improvements to your last commit, without cluttering your repository history with commit messages of the form, ``Oops, forgot to add a file'' or ``Darn, fixing a typo in last commit''. +The obvious value to amending commits is to make minor improvements to your last commit, without cluttering your repository history with commit messages of the form, "`Oops, forgot to add a file`" or "`Darn, fixing a typo in last commit`". +==== + +[NOTE] +==== +Only amend commits that are still local and have not been pushed somewhere. +Amending previously pushed commits and force pushing the branch will cause problems for your collaborators. +For more on what happens when you do this and how to recover if you're on the receiving end read <<_rebase_peril>>. ==== [[_unstaging]] @@ -60,7 +67,7 @@ Changes to be committed: modified: CONTRIBUTING.md ---- -Right below the ``Changes to be committed'' text, it says use `git reset HEAD ...` to unstage. +Right below the "`Changes to be committed`" text, it says use `git reset HEAD ...` to unstage. So, let's use that advice to unstage the `CONTRIBUTING.md` file: [source,console] @@ -129,8 +136,8 @@ You can see that the changes have been reverted. [IMPORTANT] ===== -It's important to understand that `git checkout -- ` is a dangerous command. -Any local changes you made to that file are gone -- Git just replaced that file with the most recently-committed version. +It's important to understand that `git checkout \-- ` is a dangerous command. +Any local changes you made to that file are gone -- Git just replaced that file with the last staged or committed version. Don't ever use this command unless you absolutely know that you don't want those unsaved local changes. ===== @@ -139,3 +146,90 @@ If you would like to keep the changes you've made to that file but still need to Remember, anything that is _committed_ in Git can almost always be recovered. Even commits that were on branches that were deleted or commits that were overwritten with an `--amend` commit can be recovered (see <> for data recovery). However, anything you lose that was never committed is likely never to be seen again. + +[[undoing_git_restore]] +==== Undoing things with git restore + +Git version 2.23.0 introduced a new command: `git restore`. +It's basically an alternative to `git reset` which we just covered. +From Git version 2.23.0 onwards, Git will use `git restore` instead of `git reset` for many undo operations. + +Let's retrace our steps, and undo things with `git restore` instead of `git reset`. + +===== Unstaging a Staged File with git restore + +The next two sections demonstrate how to work with your staging area and working directory changes with `git restore`. +The nice part is that the command you use to determine the state of those two areas also reminds you how to undo changes to them. +For example, let's say you've changed two files and want to commit them as two separate changes, but you accidentally type `git add *` and stage them both. +How can you unstage one of the two? +The `git status` command reminds you: + +[source,console] +---- +$ git add * +$ git status +On branch master +Changes to be committed: + (use "git restore --staged ..." to unstage) + modified: CONTRIBUTING.md + renamed: README.md -> README + +---- + +Right below the "`Changes to be committed`" text, it says use `git restore --staged ...` to unstage. +So, let's use that advice to unstage the `CONTRIBUTING.md` file: + +[source,console] +---- +$ git restore --staged CONTRIBUTING.md +$ git status +On branch master +Changes to be committed: + (use "git restore --staged ..." to unstage) + renamed: README.md -> README + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: CONTRIBUTING.md + +---- + +The `CONTRIBUTING.md` file is modified but once again unstaged. + +===== Unmodifying a Modified File with git restore + +What if you realize that you don't want to keep your changes to the `CONTRIBUTING.md` file? +How can you easily unmodify it -- revert it back to what it looked like when you last committed (or initially cloned, or however you got it into your working directory)? +Luckily, `git status` tells you how to do that, too. +In the last example output, the unstaged area looks like this: + +[source,console] +---- +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: CONTRIBUTING.md + +---- + +It tells you pretty explicitly how to discard the changes you've made. +Let's do what it says: + +[source,console] +---- +$ git restore CONTRIBUTING.md +$ git status +On branch master +Changes to be committed: + (use "git restore --staged ..." to unstage) + renamed: README.md -> README + +---- + +[IMPORTANT] +===== +It's important to understand that `git restore ` is a dangerous command. +Any local changes you made to that file are gone -- Git just replaced that file with the last staged or committed version. +Don't ever use this command unless you absolutely know that you don't want those unsaved local changes. +===== diff --git a/book/02-git-basics/sections/viewing-history.asc b/book/02-git-basics/sections/viewing-history.asc index 373cc128f..440c7f250 100644 --- a/book/02-git-basics/sections/viewing-history.asc +++ b/book/02-git-basics/sections/viewing-history.asc @@ -4,8 +4,8 @@ After you have created several commits, or if you have cloned a repository with an existing commit history, you'll probably want to look back to see what has happened. The most basic and powerful tool to do this is the `git log` command. -These examples use a very simple project called ``simplegit''. -To get the project, run +These examples use a very simple project called "`simplegit`". +To get the project, run: [source,console] ---- @@ -21,19 +21,19 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number + Change version number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 - removed unnecessary test + Remove unnecessary test commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 - first commit + Initial commit ---- By default, with no arguments, `git log` lists the commits made in that repository in reverse chronological order; that is, the most recent commits show up first. @@ -52,7 +52,7 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number + Change version number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 @@ -72,7 +72,7 @@ commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 - removed unnecessary test + Remove unnecessary test diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 @@ -101,7 +101,7 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number + Change version number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -110,7 +110,7 @@ commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 - removed unnecessary test + Remove unnecessary test lib/simplegit.rb | 5 ----- 1 file changed, 5 deletions(-) @@ -119,7 +119,7 @@ commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 - first commit + Initial commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ @@ -132,51 +132,51 @@ It also puts a summary of the information at the end. Another really useful option is `--pretty`. This option changes the log output to formats other than the default. -A few prebuilt options are available for you to use. -The `oneline` option prints each commit on a single line, which is useful if you're looking at a lot of commits. -In addition, the `short`, `full`, and `fuller` options show the output in roughly the same format but with less or more information, respectively: +A few prebuilt option values are available for you to use. +The `oneline` value for this option prints each commit on a single line, which is useful if you're looking at a lot of commits. +In addition, the `short`, `full`, and `fuller` values show the output in roughly the same format but with less or more information, respectively: [source,console] ---- $ git log --pretty=oneline -ca82a6dff817ec66f44342007202690a93763949 changed the version number -085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test -a11bef06a3f659402fe7563abf99ad00de2209e6 first commit +ca82a6dff817ec66f44342007202690a93763949 Change version number +085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Remove unnecessary test +a11bef06a3f659402fe7563abf99ad00de2209e6 Initial commit ---- -The most interesting option is `format`, which allows you to specify your own log output format. +The most interesting option value is `format`, which allows you to specify your own log output format. This is especially useful when you're generating output for machine parsing -- because you specify the format explicitly, you know it won't change with updates to Git:(((log formatting))) [source,console] ---- $ git log --pretty=format:"%h - %an, %ar : %s" -ca82a6d - Scott Chacon, 6 years ago : changed the version number -085bb3b - Scott Chacon, 6 years ago : removed unnecessary test -a11bef0 - Scott Chacon, 6 years ago : first commit +ca82a6d - Scott Chacon, 6 years ago : Change version number +085bb3b - Scott Chacon, 6 years ago : Remove unnecessary test +a11bef0 - Scott Chacon, 6 years ago : Initial commit ---- -<> lists some of the more useful options that `format` takes. +<> lists some of the more useful specifiers that `format` takes. [[pretty_format]] -.Useful options for `git log --pretty=format` +.Useful specifiers for `git log --pretty=format` [cols="1,4",options="header"] |================================ -| Option | Description of Output -| `%H` | Commit hash -| `%h` | Abbreviated commit hash -| `%T` | Tree hash -| `%t` | Abbreviated tree hash -| `%P` | Parent hashes -| `%p` | Abbreviated parent hashes -| `%an` | Author name -| `%ae` | Author email -| `%ad` | Author date (format respects the --date=option) -| `%ar` | Author date, relative -| `%cn` | Committer name -| `%ce` | Committer email -| `%cd` | Committer date -| `%cr` | Committer date, relative -| `%s` | Subject +| Specifier | Description of Output +| `%H` | Commit hash +| `%h` | Abbreviated commit hash +| `%T` | Tree hash +| `%t` | Abbreviated tree hash +| `%P` | Parent hashes +| `%p` | Abbreviated parent hashes +| `%an` | Author name +| `%ae` | Author email +| `%ad` | Author date (format respects the `--date=option`) +| `%ar` | Author date, relative +| `%cn` | Committer name +| `%ce` | Committer email +| `%cd` | Committer date +| `%cr` | Committer date, relative +| `%s` | Subject |================================ You may be wondering what the difference is between _author_ and _committer_. @@ -184,28 +184,28 @@ The author is the person who originally wrote the work, whereas the committer is So, if you send in a patch to a project and one of the core members applies the patch, both of you get credit -- you as the author, and the core member as the committer. We'll cover this distinction a bit more in <>. -The `oneline` and `format` options are particularly useful with another `log` option called `--graph`. +The `oneline` and `format` option values are particularly useful with another `log` option called `--graph`. This option adds a nice little ASCII graph showing your branch and merge history: [source,console] ---- $ git log --pretty=format:"%h %s" --graph -* 2d3acf9 ignore errors from SIGCHLD on trap -* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit +* 2d3acf9 Ignore errors from SIGCHLD on trap +* 5e3ee11 Merge branch 'master' of https://github.com/dustin/grit.git |\ -| * 420eac9 Added a method for getting the current branch. -* | 30e367c timeout code and tests -* | 5a09431 add timeout protection to grit -* | e1193f8 support for heads with slashes in them +| * 420eac9 Add method for getting the current branch +* | 30e367c Timeout code and tests +* | 5a09431 Add timeout protection to grit +* | e1193f8 Support for heads with slashes in them |/ -* d6016bc require time for xmlschema +* d6016bc Require time for xmlschema * 11d191e Merge branch 'defunkt' into local ---- This type of output will become more interesting as we go through branching and merging in the next chapter. Those are only some simple output-formatting options to `git log` -- there are many more. -<> lists the options we've covered so far, as well as some other common formatting options that may be useful, along with how they change the output of the log command. +<> lists the options we've covered so far, as well as some other common formatting options that may be useful, along with how they change the output of the `log` command. [[log_options]] .Common options to `git log` @@ -214,13 +214,13 @@ Those are only some simple output-formatting options to `git log` -- there are m | Option | Description | `-p` | Show the patch introduced with each commit. | `--stat` | Show statistics for files modified in each commit. -| `--shortstat` | Display only the changed/insertions/deletions line from the --stat command. +| `--shortstat` | Display only the changed/insertions/deletions line from the `--stat` command. | `--name-only` | Show the list of files modified after the commit information. | `--name-status` | Show the list of files affected with added/modified/deleted information as well. | `--abbrev-commit` | Show only the first few characters of the SHA-1 checksum instead of all 40. -| `--relative-date` | Display the date in a relative format (for example, ``2 weeks ago'') instead of using the full date format. +| `--relative-date` | Display the date in a relative format (for example, "`2 weeks ago`") instead of using the full date format. | `--graph` | Display an ASCII graph of the branch and merge history beside the log output. -| `--pretty` | Show commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format). +| `--pretty` | Show commits in an alternate format. Option values include `oneline`, `short`, `full`, `fuller`, and `format` (where you specify your own format). | `--oneline` | Shorthand for `--pretty=oneline --abbrev-commit` used together. |================================ @@ -246,13 +246,10 @@ The `--author` option allows you to filter on a specific author, and the `--grep [NOTE] ==== -You can specify more than one instance of both the `--author` and `--grep` search criteria, which -will limit the commit output to commits that match _any_ of the `--author` patterns and _any_ -of the `--grep` patterns; however, adding the `--all-match` option further limits the output to -just those commits that match _all_ `--grep` patterns. +You can specify more than one instance of both the `--author` and `--grep` search criteria, which will limit the commit output to commits that match _any_ of the `--author` patterns and _any_ of the `--grep` patterns; however, adding the `--all-match` option further limits the output to just those commits that match _all_ `--grep` patterns. ==== -Another really helpful filter is the `-S` option (colloquially referred to as Git's ``pickaxe'' option), which takes a string and shows only those commits that changed the number of occurrences of that string. +Another really helpful filter is the `-S` option (colloquially referred to as Git's "`pickaxe`" option), which takes a string and shows only those commits that changed the number of occurrences of that string. For instance, if you wanted to find the last commit that added or removed a reference to a specific function, you could call: [source,console] @@ -262,7 +259,12 @@ $ git log -S function_name The last really useful option to pass to `git log` as a filter is a path. If you specify a directory or file name, you can limit the log output to commits that introduced a change to those files. -This is always the last option and is generally preceded by double dashes (`--`) to separate the paths from the options. +This is always the last option and is generally preceded by double dashes (`--`) to separate the paths from the options: + +[source,console] +---- +$ git log -- path/to/file +---- In <> we'll list these and a few other common options for your reference. @@ -271,13 +273,13 @@ In <> we'll list these and a few other common options for your re [cols="2,4",options="header"] |================================ | Option | Description -| `-` | Show only the last n commits +| `-` | Show only the last n commits. | `--since`, `--after` | Limit the commits to those made after the specified date. | `--until`, `--before` | Limit the commits to those made before the specified date. | `--author` | Only show commits in which the author entry matches the specified string. | `--committer` | Only show commits in which the committer entry matches the specified string. -| `--grep` | Only show commits with a commit message containing the string -| `-S` | Only show commits adding or removing code matching the string +| `--grep` | Only show commits with a commit message containing the string. +| `-S` | Only show commits adding or removing code matching the string. |================================ For example, if you want to see which commits modifying test files in the Git source code history were committed by Junio Hamano in the month of October 2008 and are not merge commits, you can run something like this:(((log filtering))) @@ -300,5 +302,5 @@ Of the nearly 40,000 commits in the Git source code history, this command shows .Preventing the display of merge commits ==== Depending on the workflow used in your repository, it's possible that a sizable percentage of the commits in your log history are just merge commits, which typically aren't very informative. -To prevent the display of merge commits cluttering up your log history, simply add the log option `--no-merges`. +To prevent the display of merge commits cluttering up your log history, simply add the `log` option `--no-merges`. ==== diff --git a/book/03-git-branching/sections/basic-branching-and-merging.asc b/book/03-git-branching/sections/basic-branching-and-merging.asc index 80ec83e19..a894b6702 100644 --- a/book/03-git-branching/sections/basic-branching-and-merging.asc +++ b/book/03-git-branching/sections/basic-branching-and-merging.asc @@ -22,7 +22,7 @@ You'll do the following: First, let's say you're working on your project and have a couple of commits already on the `master` branch. .A simple commit history -image::images/basic-branching-1.png[A simple commit history.] +image::images/basic-branching-1.png[A simple commit history] You've decided that you're going to work on issue #53 in whatever issue-tracking system your company uses. To create a new branch and switch to it at the same time, you can run the `git checkout` command with the `-b` switch: @@ -42,7 +42,7 @@ $ git checkout iss53 ---- .Creating a new branch pointer -image::images/basic-branching-2.png[Creating a new branch pointer.] +image::images/basic-branching-2.png[Creating a new branch pointer] You work on your website and do some commits. Doing so moves the `iss53` branch forward, because you have it checked out (that is, your `HEAD` is pointing to it): @@ -50,11 +50,11 @@ Doing so moves the `iss53` branch forward, because you have it checked out (that [source,console] ---- $ vim index.html -$ git commit -a -m 'added a new footer [issue 53]' +$ git commit -a -m 'Create new footer [issue 53]' ---- .The `iss53` branch has moved forward with your work -image::images/basic-branching-3.png[The `iss53` branch has moved forward with your work.] +image::images/basic-branching-3.png[The `iss53` branch has moved forward with your work] Now you get the call that there is an issue with the website, and you need to fix it immediately. With Git, you don't have to deploy your fix along with the `iss53` changes you've made, and you don't have to put a lot of effort into reverting those changes before you can work on applying your fix to what is in production. @@ -83,13 +83,13 @@ Let's create a `hotfix` branch on which to work until it's completed: $ git checkout -b hotfix Switched to a new branch 'hotfix' $ vim index.html -$ git commit -a -m 'fixed the broken email address' -[hotfix 1fb7853] fixed the broken email address +$ git commit -a -m 'Fix broken email address' +[hotfix 1fb7853] Fix broken email address 1 file changed, 2 insertions(+) ---- .Hotfix branch based on `master` -image::images/basic-branching-4.png[Hotfix branch based on `master`.] +image::images/basic-branching-4.png[Hotfix branch based on `master`] You can run your tests, make sure the hotfix is what you want, and finally merge the `hotfix` branch back into your `master` branch to deploy to production. You do this with the `git merge` command:(((git commands, merge))) @@ -104,14 +104,14 @@ Fast-forward 1 file changed, 2 insertions(+) ---- -You'll notice the phrase ``fast-forward'' in that merge. +You'll notice the phrase "`fast-forward`" in that merge. Because the commit `C4` pointed to by the branch `hotfix` you merged in was directly ahead of the commit `C2` you're on, Git simply moves the pointer forward. -To phrase that another way, when you try to merge one commit with a commit that can be reached by following the first commit's history, Git simplifies things by moving the pointer forward because there is no divergent work to merge together -- this is called a ``fast-forward.'' +To phrase that another way, when you try to merge one commit with a commit that can be reached by following the first commit's history, Git simplifies things by moving the pointer forward because there is no divergent work to merge together -- this is called a "`fast-forward.`" Your change is now in the snapshot of the commit pointed to by the `master` branch, and you can deploy the fix. .`master` is fast-forwarded to `hotfix` -image::images/basic-branching-5.png[`master` is fast-forwarded to `hotfix`.] +image::images/basic-branching-5.png[`master` is fast-forwarded to `hotfix`] After your super-important fix is deployed, you're ready to switch back to the work you were doing before you were interrupted. However, first you'll delete the `hotfix` branch, because you no longer need it -- the `master` branch points at the same place. @@ -130,13 +130,13 @@ Now you can switch back to your work-in-progress branch on issue #53 and continu $ git checkout iss53 Switched to branch "iss53" $ vim index.html -$ git commit -a -m 'finished the new footer [issue 53]' -[iss53 ad82d7a] finished the new footer [issue 53] +$ git commit -a -m 'Finish the new footer [issue 53]' +[iss53 ad82d7a] Finish the new footer [issue 53] 1 file changed, 1 insertion(+) ---- .Work continues on `iss53` -image::images/basic-branching-6.png[Work continues on `iss53`.] +image::images/basic-branching-6.png[Work continues on `iss53`] It's worth noting here that the work you did in your `hotfix` branch is not contained in the files in your `iss53` branch. If you need to pull it in, you can merge your `master` branch into your `iss53` branch by running `git merge master`, or you can wait to integrate those changes until you decide to pull the `iss53` branch back into `master` later. @@ -165,16 +165,16 @@ Because the commit on the branch you're on isn't a direct ancestor of the branch In this case, Git does a simple three-way merge, using the two snapshots pointed to by the branch tips and the common ancestor of the two. .Three snapshots used in a typical merge -image::images/basic-merging-1.png[Three snapshots used in a typical merge.] +image::images/basic-merging-1.png[Three snapshots used in a typical merge] Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit, and is special in that it has more than one parent. .A merge commit -image::images/basic-merging-2.png[A merge commit.] +image::images/basic-merging-2.png[A merge commit] Now that your work is merged in, you have no further need for the `iss53` branch. -You can close the ticket in your ticket-tracking system, and delete the branch: +You can close the issue in your issue-tracking system, and delete the branch: [source,console] ---- @@ -265,7 +265,7 @@ Normal merge conflict for 'index.html': Hit return to start merge resolution tool (opendiff): ---- -If you want to use a merge tool other than the default (Git chose `opendiff` in this case because the command was run on a Mac), you can see all the supported tools listed at the top after ``one of the following tools.'' +If you want to use a merge tool other than the default (Git chose `opendiff` in this case because the command was run on macOS), you can see all the supported tools listed at the top after "`one of the following tools.`" Just type the name of the tool you'd rather use. [NOTE] diff --git a/book/03-git-branching/sections/branch-management.asc b/book/03-git-branching/sections/branch-management.asc index 3b384babb..ae81e89aa 100644 --- a/book/03-git-branching/sections/branch-management.asc +++ b/book/03-git-branching/sections/branch-management.asc @@ -22,9 +22,9 @@ To see the last commit on each branch, you can run `git branch -v`: [source,console] ---- $ git branch -v - iss53 93b412c fix javascript issue + iss53 93b412c Fix javascript issue * master 7a98805 Merge branch 'iss53' - testing 782fd34 add scott to the author list in the readmes + testing 782fd34 Add scott to the author list in the readme ---- The useful `--merged` and `--no-merged` options can filter this list to branches that you have or have not yet merged into the branch you're currently on. @@ -64,7 +64,7 @@ If you really do want to delete the branch and lose that work, you can force it ==== The options described above, `--merged` and `--no-merged` will, if not given a commit or branch name as an argument, show you what is, respectively, merged or not merged into your _current_ branch. -You can always provide an additional argument to ask about the merge state with respect to some other branch without checking that other branch out first, as in, what is not merged into the `master` branch? +You can always provide an additional argument to ask about the merge state with respect to some other branch without checking that other branch out first, as in, what is not merged into the `master` branch? [source,console] ---- $ git checkout testing @@ -73,3 +73,111 @@ $ git branch --no-merged master featureB ---- ==== + +==== Changing a branch name + +[CAUTION] +==== +Do not rename branches that are still in use by other collaborators. +Do not rename a branch like master/main/mainline without having read the section <<_changing_master>>. +==== + +Suppose you have a branch that is called `bad-branch-name` and you want to change it to `corrected-branch-name`, while keeping all history. +You also want to change the branch name on the remote (GitHub, GitLab, other server). +How do you do this? + +Rename the branch locally with the `git branch --move` command: + +[source, console] +---- +$ git branch --move bad-branch-name corrected-branch-name +---- + +This replaces your `bad-branch-name` with `corrected-branch-name`, but this change is only local for now. +To let others see the corrected branch on the remote, push it: + +[source,console] +---- +$ git push --set-upstream origin corrected-branch-name +---- + +Now we'll take a brief look at where we are now: + +[source, console] +---- +$ git branch --all +* corrected-branch-name + main + remotes/origin/bad-branch-name + remotes/origin/corrected-branch-name + remotes/origin/main +---- + +Notice that you're on the branch `corrected-branch-name` and it's available on the remote. +However, the branch with the bad name is also still present there but you can delete it by executing the following command: + +[source,console] +---- +$ git push origin --delete bad-branch-name +---- + +Now the bad branch name is fully replaced with the corrected branch name. + +[[_changing_master]] +===== Changing the master branch name + +[WARNING] +==== +Changing the name of a branch like master/main/mainline/default will break the integrations, services, helper utilities and build/release scripts that your repository uses. +Before you do this, make sure you consult with your collaborators. +Also, make sure you do a thorough search through your repo and update any references to the old branch name in your code and scripts. +==== + +Rename your local `master` branch into `main` with the following command: + +[source,console] +---- +$ git branch --move master main +---- + +There's no local `master` branch anymore, because it's renamed to the `main` branch. + +To let others see the new `main` branch, you need to push it to the remote. +This makes the renamed branch available on the remote. + +[source,console] +---- +$ git push --set-upstream origin main +---- + +Now we end up with the following state: + +[source,console] +---- +$ git branch --all +* main + remotes/origin/HEAD -> origin/master + remotes/origin/main + remotes/origin/master +---- + +Your local `master` branch is gone, as it's replaced with the `main` branch. +The `main` branch is present on the remote. +However, the old `master` branch is still present on the remote. +Other collaborators will continue to use the `master` branch as the base of their work, until you make some further changes. + +Now you have a few more tasks in front of you to complete the transition: + +* Any projects that depend on this one will need to update their code and/or configuration. +* Update any test-runner configuration files. +* Adjust build and release scripts. +* Redirect settings on your repo host for things like the repo's default branch, merge rules, and other things that match branch names. +* Update references to the old branch in documentation. +* Close or merge any pull requests that target the old branch. + +After you've done all these tasks, and are certain the `main` branch performs just as the `master` branch, you can delete the `master` branch: + +[source, console] +---- +$ git push origin --delete master +---- diff --git a/book/03-git-branching/sections/nutshell.asc b/book/03-git-branching/sections/nutshell.asc index 88621bbba..2bffd5ddb 100644 --- a/book/03-git-branching/sections/nutshell.asc +++ b/book/03-git-branching/sections/nutshell.asc @@ -3,18 +3,18 @@ To really understand the way Git does branching, we need to take a step back and examine how Git stores its data. -As you may remember from <>, Git doesn't store data as a series of changesets or differences, but instead as a series of _snapshots_. +As you may remember from <>, Git doesn't store data as a series of changesets or differences, but instead as a series of _snapshots_. When you make a commit, Git stores a commit object that contains a pointer to the snapshot of the content you staged. This object also contains the author's name and email address, the message that you typed, and pointers to the commit or commits that directly came before this commit (its parent or parents): zero parents for the initial commit, one parent for a normal commit, and multiple parents for a commit that results from a merge of two or more branches. To visualize this, let's assume that you have a directory containing three files, and you stage them all and commit. -Staging the files computes a checksum for each one (the SHA-1 hash we mentioned in <>), stores that version of the file in the Git repository (Git refers to them as _blobs_), and adds that checksum to the staging area: +Staging the files computes a checksum for each one (the SHA-1 hash we mentioned in <>), stores that version of the file in the Git repository (Git refers to them as _blobs_), and adds that checksum to the staging area: [source,console] ---- $ git add README test.rb LICENSE -$ git commit -m 'The initial commit of my project' +$ git commit -m 'Initial commit' ---- When you create the commit by running `git commit`, Git checksums each subdirectory (in this case, just the root project directory) and stores them as a tree object in the Git repository. @@ -23,12 +23,12 @@ Git then creates a commit object that has the metadata and a pointer to the root Your Git repository now contains five objects: three _blobs_ (each representing the contents of one of the three files), one _tree_ that lists the contents of the directory and specifies which file names are stored as which blobs, and one _commit_ with the pointer to that root tree and all the commit metadata. .A commit and its tree -image::images/commit-and-tree.png[A commit and its tree.] +image::images/commit-and-tree.png[A commit and its tree] If you make some changes and commit again, the next commit stores a pointer to the commit that came immediately before it. .Commits and their parents -image::images/commits-and-parents.png[Commits and their parents.] +image::images/commits-and-parents.png[Commits and their parents] A branch in Git is simply a lightweight movable pointer to one of these commits. The default branch name in Git is `master`. @@ -37,13 +37,13 @@ Every time you commit, the `master` branch pointer moves forward automatically. [NOTE] ==== -The ``master'' branch in Git is not a special branch.(((master))) +The "`master`" branch in Git is not a special branch.(((master))) It is exactly like any other branch. The only reason nearly every repository has one is that the `git init` command creates it by default and most people don't bother to change it. ==== .A branch and its commit history -image::images/branch-and-history.png[A branch and its commit history.] +image::images/branch-and-history.png[A branch and its commit history] [[_create_new_branch]] ==== Creating a New Branch @@ -62,7 +62,7 @@ $ git branch testing This creates a new pointer to the same commit you're currently on. .Two branches pointing into the same series of commits -image::images/two-branches.png[Two branches pointing into the same series of commits.] +image::images/two-branches.png[Two branches pointing into the same series of commits] How does Git know what branch you're currently on? It keeps a special pointer called `HEAD`. @@ -72,7 +72,7 @@ In this case, you're still on `master`. The `git branch` command only _created_ a new branch -- it didn't switch to that branch. .HEAD pointing to a branch -image::images/head-to-master.png[HEAD pointing to a branch.] +image::images/head-to-master.png[HEAD pointing to a branch] You can easily see this by running a simple `git log` command that shows you where the branch pointers are pointing. This option is called `--decorate`. @@ -80,12 +80,12 @@ This option is called `--decorate`. [source,console] ---- $ git log --oneline --decorate -f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface -34ac2 Fixed bug #1328 - stack overflow under certain conditions -98ca9 The initial commit of my project +f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface +34ac2 Fix bug #1328 - stack overflow under certain conditions +98ca9 Initial commit ---- -You can see the ``master'' and ``testing'' branches that are right there next to the `f30ab` commit. +You can see the `master` and `testing` branches that are right there next to the `f30ab` commit. [[_switching_branches]] ==== Switching Branches @@ -102,7 +102,7 @@ $ git checkout testing This moves `HEAD` to point to the `testing` branch. .HEAD points to the current branch -image::images/head-to-testing.png[HEAD points to the current branch.] +image::images/head-to-testing.png[HEAD points to the current branch] What is the significance of that? Well, let's do another commit: @@ -110,11 +110,11 @@ Well, let's do another commit: [source,console] ---- $ vim test.rb -$ git commit -a -m 'made a change' +$ git commit -a -m 'Make a change' ---- .The HEAD branch moves forward when a commit is made -image::images/advance-testing.png[The HEAD branch moves forward when a commit is made.] +image::images/advance-testing.png[The HEAD branch moves forward when a commit is made] This is interesting, because now your `testing` branch has moved forward, but your `master` branch still points to the commit you were on when you ran `git checkout` to switch branches. Let's switch back to the `master` branch: @@ -124,8 +124,20 @@ Let's switch back to the `master` branch: $ git checkout master ---- +[NOTE] +.`git log` doesn't show _all_ the branches _all_ the time +==== +If you were to run `git log` right now, you might wonder where the "testing" branch you just created went, as it would not appear in the output. + +The branch hasn't disappeared; Git just doesn't know that you're interested in that branch and it is trying to show you what it thinks you're interested in. +In other words, by default, `git log` will only show commit history below the branch you've checked out. + +To show commit history for the desired branch you have to explicitly specify it: `git log testing`. +To show all of the branches, add `--all` to your `git log` command. +==== + .HEAD moves when you checkout -image::images/checkout-master.png[HEAD moves when you checkout.] +image::images/checkout-master.png[HEAD moves when you checkout] That command did two things. It moved the HEAD pointer back to point to the `master` branch, and it reverted the files in your working directory back to the snapshot that `master` points to. @@ -145,7 +157,7 @@ Let's make a few changes and commit again: [source,console] ---- $ vim test.rb -$ git commit -a -m 'made other changes' +$ git commit -a -m 'Make other changes' ---- Now your project history has diverged (see <>). @@ -155,7 +167,7 @@ And you did all that with simple `branch`, `checkout`, and `commit` commands. [[divergent_history]] .Divergent history -image::images/advance-master.png[Divergent history.] +image::images/advance-master.png[Divergent history] You can also see this easily with the `git log` command. If you run `git log --oneline --decorate --graph --all` it will print out the history of your commits, showing where your branch pointers are and how your history has diverged. @@ -163,12 +175,12 @@ If you run `git log --oneline --decorate --graph --all` it will print out the hi [source,console] ---- $ git log --oneline --decorate --graph --all -* c2b9e (HEAD, master) made other changes -| * 87ab2 (testing) made a change +* c2b9e (HEAD, master) Make other changes +| * 87ab2 (testing) Make a change |/ -* f30ab add feature #32 - ability to add new formats to the -* 34ac2 fixed bug #1328 - stack overflow under certain conditions -* 98ca9 initial commit of my project +* f30ab Add feature #32 - ability to add new formats to the central interface +* 34ac2 Fix bug #1328 - stack overflow under certain conditions +* 98ca9 Initial commit of my project ---- Because a branch in Git is actually a simple file that contains the 40 character SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. @@ -186,3 +198,13 @@ Let's see why you should do so. ==== It's typical to create a new branch and want to switch to that new branch at the same time -- this can be done in one operation with `git checkout -b `. ==== + +[NOTE] +==== +From Git version 2.23 onwards you can use `git switch` instead of `git checkout` to: + +- Switch to an existing branch: `git switch testing-branch`. +- Create a new branch and switch to it: `git switch -c new-branch`. + The `-c` flag stands for create, you can also use the full flag: `--create`. +- Return to your previously checked out branch: `git switch -`. +==== diff --git a/book/03-git-branching/sections/rebasing.asc b/book/03-git-branching/sections/rebasing.asc index c9e48ede9..c66535246 100644 --- a/book/03-git-branching/sections/rebasing.asc +++ b/book/03-git-branching/sections/rebasing.asc @@ -10,14 +10,14 @@ In this section you'll learn what rebasing is, how to do it, why it's a pretty a If you go back to an earlier example from <<_basic_merging>>, you can see that you diverged your work and made commits on two different branches. .Simple divergent history -image::images/basic-rebase-1.png[Simple divergent history.] +image::images/basic-rebase-1.png[Simple divergent history] The easiest way to integrate the branches, as we've already covered, is the `merge` command. It performs a three-way merge between the two latest branch snapshots (`C3` and `C4`) and the most recent common ancestor of the two (`C2`), creating a new snapshot (and commit). [[rebasing-merging-example]] .Merging to integrate diverged work history -image::images/basic-rebase-2.png[Merging to integrate diverged work history.] +image::images/basic-rebase-2.png[Merging to integrate diverged work history] However, there is another way: you can take the patch of the change that was introduced in `C4` and reapply it on top of `C3`. In Git, this is called _rebasing_. @@ -36,7 +36,7 @@ Applying: added staged command This operation works by going to the common ancestor of the two branches (the one you're on and the one you're rebasing onto), getting the diff introduced by each commit of the branch you're on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn. .Rebasing the change introduced in `C4` onto `C3` -image::images/basic-rebase-3.png[Rebasing the change introduced in `C4` onto `C3`.] +image::images/basic-rebase-3.png[Rebasing the change introduced in `C4` onto `C3`] At this point, you can go back to the `master` branch and do a fast-forward merge. @@ -46,8 +46,8 @@ $ git checkout master $ git merge experiment ---- -.Fast-forwarding the master branch -image::images/basic-rebase-4.png[Fast-forwarding the master branch.] +.Fast-forwarding the `master` branch +image::images/basic-rebase-4.png[Fast-forwarding the `master` branch] Now, the snapshot pointed to by `C4'` is exactly the same as the one that was pointed to by `C5` in <>. There is no difference in the end product of the integration, but rebasing makes for a cleaner history. @@ -66,25 +66,25 @@ You can also have your rebase replay on something other than the rebase target b Take a history like <>, for example. You branched a topic branch (`server`) to add some server-side functionality to your project, and made a commit. Then, you branched off that to make the client-side changes (`client`) and committed a few times. -Finally, you went back to your server branch and did a few more commits. +Finally, you went back to your `server` branch and did a few more commits. [[rbdiag_e]] .A history with a topic branch off another topic branch -image::images/interesting-rebase-1.png[A history with a topic branch off another topic branch.] +image::images/interesting-rebase-1.png[A history with a topic branch off another topic branch] Suppose you decide that you want to merge your client-side changes into your mainline for a release, but you want to hold off on the server-side changes until it's tested further. -You can take the changes on client that aren't on server (`C8` and `C9`) and replay them on your `master` branch by using the `--onto` option of `git rebase`: +You can take the changes on `client` that aren't on `server` (`C8` and `C9`) and replay them on your `master` branch by using the `--onto` option of `git rebase`: [source,console] ---- $ git rebase --onto master server client ---- -This basically says, ``Take the `client` branch, figure out the patches since it diverged from the `server` branch, and replay these patches in the `client` branch as if it was based directly off the `master` branch instead.'' +This basically says, "`Take the `client` branch, figure out the patches since it diverged from the `server` branch, and replay these patches in the `client` branch as if it was based directly off the `master` branch instead.`" It's a bit complex, but the result is pretty cool. .Rebasing a topic branch off another topic branch -image::images/interesting-rebase-2.png[Rebasing a topic branch off another topic branch.] +image::images/interesting-rebase-2.png[Rebasing a topic branch off another topic branch] Now you can fast-forward your `master` branch (see <>): @@ -95,11 +95,11 @@ $ git merge client ---- [[rbdiag_g]] -.Fast-forwarding your master branch to include the client branch changes -image::images/interesting-rebase-3.png[Fast-forwarding your master branch to include the client branch changes.] +.Fast-forwarding your `master` branch to include the `client` branch changes +image::images/interesting-rebase-3.png[Fast-forwarding your `master` branch to include the `client` branch changes] -Let's say you decide to pull in your server branch as well. -You can rebase the server branch onto the `master` branch without having to check it out first by running `git rebase ` -- which checks out the topic branch (in this case, `server`) for you and replays it onto the base branch (`master`): +Let's say you decide to pull in your `server` branch as well. +You can rebase the `server` branch onto the `master` branch without having to check it out first by running `git rebase ` -- which checks out the topic branch (in this case, `server`) for you and replays it onto the base branch (`master`): [source,console] ---- @@ -109,8 +109,8 @@ $ git rebase master server This replays your `server` work on top of your `master` work, as shown in <>. [[rbdiag_h]] -.Rebasing your server branch on top of your master branch -image::images/interesting-rebase-4.png[Rebasing your server branch on top of your master branch.] +.Rebasing your `server` branch on top of your `master` branch +image::images/interesting-rebase-4.png[Rebasing your `server` branch on top of your `master` branch] Then, you can fast-forward the base branch (`master`): @@ -130,7 +130,7 @@ $ git branch -d server [[rbdiag_i]] .Final commit history -image::images/interesting-rebase-5.png[Final commit history.] +image::images/interesting-rebase-5.png[Final commit history] [[_rebase_peril]] ==== The Perils of Rebasing @@ -138,7 +138,7 @@ image::images/interesting-rebase-5.png[Final commit history.] (((rebasing, perils of))) Ahh, but the bliss of rebasing isn't without its drawbacks, which can be summed up in a single line: -*Do not rebase commits that exist outside your repository and people may have based work on them.* +*Do not rebase commits that exist outside your repository and that people may have based work on.* If you follow that guideline, you'll be fine. If you don't, people will hate you, and you'll be scorned by friends and family. @@ -151,27 +151,27 @@ Suppose you clone from a central server and then do some work off that. Your commit history looks like this: .Clone a repository, and base some work on it -image::images/perils-of-rebasing-1.png["Clone a repository, and base some work on it."] +image::images/perils-of-rebasing-1.png["Clone a repository, and base some work on it"] Now, someone else does more work that includes a merge, and pushes that work to the central server. You fetch it and merge the new remote branch into your work, making your history look something like this: .Fetch more commits, and merge them into your work -image::images/perils-of-rebasing-2.png["Fetch more commits, and merge them into your work."] +image::images/perils-of-rebasing-2.png["Fetch more commits, and merge them into your work"] Next, the person who pushed the merged work decides to go back and rebase their work instead; they do a `git push --force` to overwrite the history on the server. You then fetch from that server, bringing down the new commits. [[_pre_merge_rebase_work]] .Someone pushes rebased commits, abandoning commits you've based your work on -image::images/perils-of-rebasing-3.png["Someone pushes rebased commits, abandoning commits you've based your work on."] +image::images/perils-of-rebasing-3.png["Someone pushes rebased commits, abandoning commits you've based your work on"] Now you're both in a pickle. If you do a `git pull`, you'll create a merge commit which includes both lines of history, and your repository will look like this: [[_merge_rebase_work]] .You merge in the same work again into a new merge commit -image::images/perils-of-rebasing-4.png[You merge in the same work again into a new merge commit.] +image::images/perils-of-rebasing-4.png[You merge in the same work again into a new merge commit] If you run a `git log` when your history looks like this, you'll see two commits that have the same author, date, and message, which will be confusing. Furthermore, if you push this history back up to the server, you'll reintroduce all those rebased commits to the central server, which can further confuse people. @@ -184,25 +184,25 @@ If you *do* find yourself in a situation like this, Git has some further magic t If someone on your team force pushes changes that overwrite work that you've based work on, your challenge is to figure out what is yours and what they've rewritten. It turns out that in addition to the commit SHA-1 checksum, Git also calculates a checksum that is based just on the patch introduced with the commit. -This is called a ``patch-id''. +This is called a "`patch-id`". If you pull down work that was rewritten and rebase it on top of the new commits from your partner, Git can often successfully figure out what is uniquely yours and apply them back on top of the new branch. For instance, in the previous scenario, if instead of doing a merge when we're at <<_pre_merge_rebase_work>> we run `git rebase teamone/master`, Git will: -* Determine what work is unique to our branch (C2, C3, C4, C6, C7) -* Determine which are not merge commits (C2, C3, C4) -* Determine which have not been rewritten into the target branch (just C2 and C3, since C4 is the same patch as C4') +* Determine what work is unique to our branch (`C2`, `C3`, `C4`, `C6`, `C7`) +* Determine which are not merge commits (`C2`, `C3`, `C4`) +* Determine which have not been rewritten into the target branch (just `C2` and `C3`, since `C4` is the same patch as `C4'`) * Apply those commits to the top of `teamone/master` So instead of the result we see in <<_merge_rebase_work>>, we would end up with something more like <<_rebase_rebase_work>>. [[_rebase_rebase_work]] -.Rebase on top of force-pushed rebase work. -image::images/perils-of-rebasing-5.png[Rebase on top of force-pushed rebase work.] +.Rebase on top of force-pushed rebase work +image::images/perils-of-rebasing-5.png[Rebase on top of force-pushed rebase work] -This only works if C4 and C4' that your partner made are almost exactly the same patch. -Otherwise the rebase won't be able to tell that it's a duplicate and will add another C4-like patch (which will probably fail to apply cleanly, since the changes would already be at least somewhat there). +This only works if `C4` and `C4'` that your partner made are almost exactly the same patch. +Otherwise the rebase won't be able to tell that it's a duplicate and will add another `C4`-like patch (which will probably fail to apply cleanly, since the changes would already be at least somewhat there). You can also simplify this by running a `git pull --rebase` instead of a normal `git pull`. Or you could do it manually with a `git fetch` followed by a `git rebase teamone/master` in this case. @@ -228,11 +228,13 @@ So what if there was a messy series of merge commits? That's how it happened, and the repository should preserve that for posterity. The opposing point of view is that the commit history is the *story of how your project was made.* -You wouldn't publish the first draft of a book, and the manual for how to maintain your software deserves careful editing. -This is the camp that uses tools like rebase and filter-branch to tell the story in the way that's best for future readers. +You wouldn't publish the first draft of a book, so why show your messy work? +When you're working on a project, you may need a record of all your missteps and dead-end paths, but when it's time to show your work to the world, you may want to tell a more coherent story of how to get from A to B. +People in this camp use tools like `rebase` and `filter-branch` to rewrite their commits before they're merged into the mainline branch. +They use tools like `rebase` and `filter-branch`, to tell the story in the way that's best for future readers. Now, to the question of whether merging or rebasing is better: hopefully you'll see that it's not that simple. Git is a powerful tool, and allows you to do many things to and with your history, but every team and every project is different. Now that you know how both of these things work, it's up to you to decide which one is best for your particular situation. -In general the way to get the best of both worlds is to rebase local changes you've made but haven't shared yet before you push them in order to clean up your story, but never rebase anything you've pushed somewhere. +You can get the best of both worlds: rebase local changes before pushing to clean up your work, but never rebase anything that you've pushed somewhere. diff --git a/book/03-git-branching/sections/remote-branches.asc b/book/03-git-branching/sections/remote-branches.asc index 1a81ba1ff..adbb8735d 100644 --- a/book/03-git-branching/sections/remote-branches.asc +++ b/book/03-git-branching/sections/remote-branches.asc @@ -3,7 +3,7 @@ (((branches, remote)))(((references, remote))) Remote references are references (pointers) in your remote repositories, including branches, tags, and so on. -You can get a full list of remote references explicitly with `git ls-remote [remote]`, or `git remote show [remote]` for remote branches as well as more information. +You can get a full list of remote references explicitly with `git ls-remote `, or `git remote show ` for remote branches as well as more information. Nevertheless, a more common way is to take advantage of remote-tracking branches. Remote-tracking branches are references to the state of remote branches. @@ -20,27 +20,27 @@ If you clone from this, Git's `clone` command automatically names it `origin` fo Git also gives you your own local `master` branch starting at the same place as origin's `master` branch, so you have something to work from. [NOTE] -.``origin'' is not special +."`origin`" is not special ==== -Just like the branch name ``master'' does not have any special meaning in Git, neither does ``origin''. -While ``master'' is the default name for a starting branch when you run `git init` which is the only reason it's widely used, ``origin'' is the default name for a remote when you run `git clone`. +Just like the branch name "`master`" does not have any special meaning in Git, neither does "`origin`". +While "`master`" is the default name for a starting branch when you run `git init` which is the only reason it's widely used, "`origin`" is the default name for a remote when you run `git clone`. If you run `git clone -o booyah` instead, then you will have `booyah/master` as your default remote branch.(((origin))) ==== .Server and local repositories after cloning -image::images/remote-branches-1.png[Server and local repositories after cloning.] +image::images/remote-branches-1.png[Server and local repositories after cloning] If you do some work on your local `master` branch, and, in the meantime, someone else pushes to `git.ourcompany.com` and updates its `master` branch, then your histories move forward differently. -Also, as long as you stay out of contact with your origin server, your `origin/master` pointer doesn't move. +Also, as long as you stay out of contact with your `origin` server, your `origin/master` pointer doesn't move. .Local and remote work can diverge -image::images/remote-branches-2.png[Local and remote work can diverge.] +image::images/remote-branches-2.png[Local and remote work can diverge] To synchronize your work with a given remote, you run a `git fetch ` command (in our case, `git fetch origin`). -This command looks up which server ``origin'' is (in this case, it's `git.ourcompany.com`), fetches any data from it that you don't yet have, and updates your local database, moving your `origin/master` pointer to its new, more up-to-date position. +This command looks up which server "`origin`" is (in this case, it's `git.ourcompany.com`), fetches any data from it that you don't yet have, and updates your local database, moving your `origin/master` pointer to its new, more up-to-date position. .`git fetch` updates your remote-tracking branches -image::images/remote-branches-3.png[`git fetch` updates your remote references.] +image::images/remote-branches-3.png[`git fetch` updates your remote-tracking branches] To demonstrate having multiple remote servers and what remote branches for those remote projects look like, let's assume you have another internal Git server that is used only for development by one of your sprint teams. This server is at `git.team1.ourcompany.com`. @@ -48,13 +48,13 @@ You can add it as a new remote reference to the project you're currently working Name this remote `teamone`, which will be your shortname for that whole URL. .Adding another server as a remote -image::images/remote-branches-4.png[Adding another server as a remote.] +image::images/remote-branches-4.png[Adding another server as a remote] Now, you can run `git fetch teamone` to fetch everything the remote `teamone` server has that you don't have yet. Because that server has a subset of the data your `origin` server has right now, Git fetches no data but sets a remote-tracking branch called `teamone/master` to point to the commit that `teamone` has as its `master` branch. .Remote-tracking branch for `teamone/master` -image::images/remote-branches-5.png[Remote tracking branch for `teamone/master`.] +image::images/remote-branches-5.png[Remote-tracking branch for `teamone/master`] [[_pushing_branches]] ==== Pushing @@ -80,9 +80,9 @@ To https://github.com/schacon/simplegit ---- This is a bit of a shortcut. -Git automatically expands the `serverfix` branchname out to `refs/heads/serverfix:refs/heads/serverfix`, which means, ``Take my serverfix local branch and push it to update the remote's serverfix branch.'' +Git automatically expands the `serverfix` branchname out to `refs/heads/serverfix:refs/heads/serverfix`, which means, "`Take my `serverfix` local branch and push it to update the remote's `serverfix` branch.`" We'll go over the `refs/heads/` part in detail in <>, but you can generally leave it off. -You can also do `git push origin serverfix:serverfix`, which does the same thing -- it says, ``Take my serverfix and make it the remote's serverfix.'' +You can also do `git push origin serverfix:serverfix`, which does the same thing -- it says, "`Take my serverfix and make it the remote's serverfix.`" You can use this format to push a local branch into a remote branch that is named differently. If you didn't want it to be called `serverfix` on the remote, you could instead run `git push origin serverfix:awesomebranch` to push your local `serverfix` branch to the `awesomebranch` branch on the remote project. @@ -92,7 +92,7 @@ If you didn't want it to be called `serverfix` on the remote, you could instead If you're using an HTTPS URL to push over, the Git server will ask you for your username and password for authentication. By default it will prompt you on the terminal for this information so the server can tell if you're allowed to push. -If you don't want to type it every single time you push, you can set up a ``credential cache''. +If you don't want to type it every single time you push, you can set up a "`credential cache`". The simplest is just to keep it in memory for a few minutes, which you can easily set up by running `git config --global credential.helper cache`. For more information on the various credential caching options available, see <>. @@ -130,7 +130,7 @@ This gives you a local branch that you can work on that starts where `origin/ser ==== Tracking Branches (((branches, tracking)))(((branches, upstream))) -Checking out a local branch from a remote-tracking branch automatically creates what is called a ``tracking branch'' (and the branch it tracks is called an ``upstream branch''). +Checking out a local branch from a remote-tracking branch automatically creates what is called a "`tracking branch`" (and the branch it tracks is called an "`upstream branch`"). Tracking branches are local branches that have a direct relationship to a remote branch. If you're on a tracking branch and type `git pull`, Git automatically knows which server to fetch from and which branch to merge in. @@ -179,7 +179,7 @@ Branch serverfix set up to track remote branch serverfix from origin. .Upstream shorthand ==== When you have a tracking branch set up, you can reference its upstream branch with the `@{upstream}` or `@{u}` shorthand. -So if you're on the `master` branch and it's tracking `origin/master`, you can say something like `git merge @{u}` instead of `git merge origin/master` if you wish.(((+++@{u}+++)))(((+++@{upstream}+++))) +So if you're on the `master` branch and it's tracking `origin/master`, you can say something like `git merge @{u}` instead of `git merge origin/master` if you wish.(((@{u})))(((@{upstream}))) ==== If you want to see what tracking branches you have set up, you can use the `-vv` option to `git branch`. @@ -188,13 +188,13 @@ This will list out your local branches with more information including what each [source,console] ---- $ git branch -vv - iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets - master 1ae2a45 [origin/master] deploying index fix -* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it - testing 5ea463a trying something new + iss53 7e424c3 [origin/iss53: ahead 2] Add forgotten brackets + master 1ae2a45 [origin/master] Deploy index fix +* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it + testing 5ea463a Try something new ---- -So here we can see that our `iss53` branch is tracking `origin/iss53` and is ``ahead'' by two, meaning that we have two commits locally that are not pushed to the server. +So here we can see that our `iss53` branch is tracking `origin/iss53` and is "`ahead`" by two, meaning that we have two commits locally that are not pushed to the server. We can also see that our `master` branch is tracking `origin/master` and is up to date. Next we can see that our `serverfix` branch is tracking the `server-fix-good` branch on our `teamone` server and is ahead by three and behind by one, meaning that there is one commit on the server we haven't merged in yet and three commits locally that we haven't pushed. Finally we can see that our `testing` branch is not tracking any remote branch. @@ -217,8 +217,6 @@ It will simply get the data for you and let you merge it yourself. However, there is a command called `git pull` which is essentially a `git fetch` immediately followed by a `git merge` in most cases. If you have a tracking branch set up as demonstrated in the last section, either by explicitly setting it or by having it created for you by the `clone` or `checkout` commands, `git pull` will look up what server and branch your current branch is tracking, fetch from that server and then try to merge in that remote branch. -Generally it's better to simply use the `fetch` and `merge` commands explicitly as the magic of `git pull` can often be confusing. - [[_delete_branches]] ==== Deleting Remote Branches @@ -234,5 +232,5 @@ To https://github.com/schacon/simplegit - [deleted] serverfix ---- -Basically all this does is remove the pointer from the server. +Basically all this does is to remove the pointer from the server. The Git server will generally keep the data there for a while until a garbage collection runs, so if it was accidentally deleted, it's often easy to recover. diff --git a/book/03-git-branching/sections/workflows.asc b/book/03-git-branching/sections/workflows.asc index 4ae66a76d..9e6f3922a 100644 --- a/book/03-git-branching/sections/workflows.asc +++ b/book/03-git-branching/sections/workflows.asc @@ -17,13 +17,13 @@ In reality, we're talking about pointers moving up the line of commits you're ma The stable branches are farther down the line in your commit history, and the bleeding-edge branches are farther up the history. .A linear view of progressive-stability branching -image::images/lr-branches-1.png[A linear view of progressive-stability branching.] +image::images/lr-branches-1.png[A linear view of progressive-stability branching] It's generally easier to think about them as work silos, where sets of commits graduate to a more stable silo when they're fully tested. [[lrbranch_b]] -.A ``silo'' view of progressive-stability branching -image::images/lr-branches-2.png[A ``silo'' view of progressive-stability branching.] +.A "`silo`" view of progressive-stability branching +image::images/lr-branches-2.png[A “silo” view of progressive-stability branching] You can keep doing this for several levels of stability. Some larger projects also have a `proposed` or `pu` (proposed updates) branch that has integrated branches that may not be ready to go into the `next` or `master` branch. @@ -48,14 +48,14 @@ Consider an example of doing some work (on `master`), branching off for an issue Your commit history will look something like this: .Multiple topic branches -image::images/topic-branches-1.png[Multiple topic branches.] +image::images/topic-branches-1.png[Multiple topic branches] Now, let's say you decide you like the second solution to your issue best (`iss91v2`); and you showed the `dumbidea` branch to your coworkers, and it turns out to be genius. You can throw away the original `iss91` branch (losing commits `C5` and `C6`) and merge in the other two. Your history then looks like this: .History after merging `dumbidea` and `iss91v2` -image::images/topic-branches-2.png[History after merging `dumbidea` and `iss91v2`.] +image::images/topic-branches-2.png[History after merging `dumbidea` and `iss91v2`] We will go into more detail about the various possible workflows for your Git project in <>, so before you decide which branching scheme your next project will use, be sure to read that chapter. diff --git a/book/04-git-server/sections/generating-ssh-key.asc b/book/04-git-server/sections/generating-ssh-key.asc index 6ed59b1f3..d1a61daf4 100644 --- a/book/04-git-server/sections/generating-ssh-key.asc +++ b/book/04-git-server/sections/generating-ssh-key.asc @@ -54,4 +54,4 @@ mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx NrRFi9wrf+M7Q== schacon@mylaptop.local ---- -For a more in-depth tutorial on creating an SSH key on multiple operating systems, see the GitHub guide on SSH keys at https://help.github.com/articles/generating-ssh-keys[]. +For a more in-depth tutorial on creating an SSH key on multiple operating systems, see the GitHub guide on SSH keys at https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent[^]. diff --git a/book/04-git-server/sections/git-daemon.asc b/book/04-git-server/sections/git-daemon.asc index 1bc425770..1fe172375 100644 --- a/book/04-git-server/sections/git-daemon.asc +++ b/book/04-git-server/sections/git-daemon.asc @@ -1,7 +1,7 @@ === Git Daemon (((serving repositories, git protocol))) -Next we'll set up a daemon serving repositories using the ``Git'' protocol. +Next we'll set up a daemon serving repositories using the "`Git`" protocol. This is a common choice for fast, unauthenticated access to your Git data. Remember that since this is not an authenticated service, anything you serve over this protocol is public within its network. diff --git a/book/04-git-server/sections/git-on-a-server.asc b/book/04-git-server/sections/git-on-a-server.asc index 18727c660..61847a993 100644 --- a/book/04-git-server/sections/git-on-a-server.asc +++ b/book/04-git-server/sections/git-on-a-server.asc @@ -23,7 +23,7 @@ done. You should now have a copy of the Git directory data in your `my_project.git` directory. -This is roughly equivalent to something like +This is roughly equivalent to something like: [source,console] ---- @@ -45,7 +45,7 @@ Assuming that `/srv/git` exists on that server, you can set up your new reposito $ scp -r my_project.git user@git.example.com:/srv/git ---- -At this point, other users who have SSH-based read access to the `/srv/git` directory on that server can clone your repository by running +At this point, other users who have SSH-based read access to the `/srv/git` directory on that server can clone your repository by running: [source,console] ---- diff --git a/book/04-git-server/sections/gitlab.asc b/book/04-git-server/sections/gitlab.asc index a17d0e5d0..97de78937 100644 --- a/book/04-git-server/sections/gitlab.asc +++ b/book/04-git-server/sections/gitlab.asc @@ -2,77 +2,76 @@ (((serving repositories, GitLab)))(((GitLab))) GitWeb is pretty simplistic though. -If you're looking for a more modern, fully featured Git server, there are some several open source solutions out there that you can install instead. -As GitLab is one of the more popular ones, we'll cover installing and using it as an example. -This is a bit more complex than the GitWeb option and likely requires more maintenance, but it is a much more fully featured option. +If you're looking for a modern, fully featured Git server, there are several open source solutions out there that you can install instead. +As GitLab is one of the popular ones, we'll cover installing and using it as an example. +This is harder than the GitWeb option and will require more maintenance, but it is a fully featured option. ==== Installation -GitLab is a database-backed web application, so its installation is a bit more involved than some other Git servers. -Fortunately, this process is very well-documented and supported. +GitLab is a database-backed web application, so its installation is more involved than some other Git servers. +Fortunately, this process is well-documented and supported. +GitLab strongly recommends installing GitLab on your server via the official Omnibus GitLab package. -There are a few methods you can pursue to install GitLab. -To get something up and running quickly, you can download a virtual machine image or a one-click installer from https://bitnami.com/stack/gitlab[], and tweak the configuration to match your particular environment.(((bitnami))) -One nice touch Bitnami has included is the login screen (accessed by typing alt+→); it tells you the IP address and default username and password for the installed GitLab. +The other installation options are: -[[bitnami]] -.The Bitnami GitLab virtual machine login screen. -image::images/bitnami.png[The Bitnami GitLab virtual machine login screen.] +* GitLab Helm chart, for use with Kubernetes. +* Dockerized GitLab packages for use with Docker. +* From the source files. +* Cloud providers such as AWS, Google Cloud Platform, Azure, OpenShift and Digital Ocean. -For anything else, follow the guidance in the GitLab Community Edition readme, which can be found at https://gitlab.com/gitlab-org/gitlab-ce/tree/master[]. -There you'll find assistance for installing GitLab using Chef recipes, a virtual machine on Digital Ocean, and RPM and DEB packages (which, as of this writing, are in beta). -There's also ``unofficial'' guidance on getting GitLab running with non-standard operating systems and databases, a fully-manual installation script, and many other topics. +For more information read the https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/README.md[GitLab Community Edition (CE) readme^]. ==== Administration GitLab's administration interface is accessed over the web. -Simply point your browser to the hostname or IP address where GitLab is installed, and log in as an admin user. -The default username is `admin@local.host`, and the default password is `5iveL!fe` (which you will be prompted to change as soon as you enter it). -Once logged in, click the ``Admin area'' icon in the menu at the top right. +Simply point your browser to the hostname or IP address where GitLab is installed, and log in as the `root` user. +The password will depend on your installation type but by default, Omnibus GitLab automatically generates a password for and stores it to /etc/gitlab/initial_root_password for at least 24 hours. +Follow the documentation for more details. +After you've logged in, click the "`Admin area`" icon in the menu at the top right. [[gitlab_menu]] -.The ``Admin area'' item in the GitLab menu. -image::images/gitlab-menu.png[The ``Admin area'' item in the GitLab menu.] +.The "`Admin area`" item in the GitLab menu +image::images/gitlab-menu.png[The “Admin area” item in the GitLab menu] ===== Users -Users in GitLab are accounts that correspond to people. -User accounts don't have a lot of complexity; mainly it's a collection of personal information attached to login data. -Each user account comes with a *namespace*, which is a logical grouping of projects that belong to that user. -If the user +jane+ had a project named +project+, that project's url would be `http://server/jane/project`. +Everybody using your GitLab server must have a user account. +User accounts are quite simple, they mainly contain personal information attached to login data. +Each user account has a *namespace*, which is a logical grouping of projects that belong to that user. +If the user +jane+ had a project named +project+, that project's URL would be `http://server/jane/project`. [[gitlab_users]] -.The GitLab user administration screen. -image::images/gitlab-users.png[The GitLab user administration screen.] +.The GitLab user administration screen +image::images/gitlab-users.png[The GitLab user administration screen] -Removing a user can be done in two ways. -``Blocking'' a user prevents them from logging into the GitLab instance, but all of the data under that user's namespace will be preserved, and commits signed with that user's email address will still link back to their profile. +You can remove a user account in two ways: +"`Blocking`" a user prevents them from logging into the GitLab instance, but all of the data under that user's namespace will be preserved, and commits signed with that user's email address will still link back to their profile. -``Destroying'' a user, on the other hand, completely removes them from the database and filesystem. +"`Destroying`" a user, on the other hand, completely removes them from the database and filesystem. All projects and data in their namespace is removed, and any groups they own will also be removed. -This is obviously a much more permanent and destructive action, and its uses are rare. +This is obviously a much more permanent and destructive action, and you will rarely need it. [[_gitlab_groups_section]] ===== Groups -A GitLab group is an assemblage of projects, along with data about how users can access those projects. -Each group has a project namespace (the same way that users do), so if the group +training+ has a project +materials+, its url would be `http://server/training/materials`. +A GitLab group is a collection of projects, along with data about how users can access those projects. +Each group has a project namespace (the same way that users do), so if the group +training+ has a project +materials+, its URL would be `http://server/training/materials`. [[gitlab_groups]] -.The GitLab group administration screen. -image::images/gitlab-groups.png[The GitLab group administration screen.] +.The GitLab group administration screen +image::images/gitlab-groups.png[The GitLab group administration screen] Each group is associated with a number of users, each of which has a level of permissions for the group's projects and the group itself. -These range from ``Guest'' (issues and chat only) to ``Owner'' (full control of the group, its members, and its projects). +These range from "`Guest`" (issues and chat only) to "`Owner`" (full control of the group, its members, and its projects). The types of permissions are too numerous to list here, but GitLab has a helpful link on the administration screen. ===== Projects A GitLab project roughly corresponds to a single Git repository. Every project belongs to a single namespace, either a user or a group. -If the project belongs to a user, the owner of the project has direct control over who has access to the project; if the project belongs to a group, the group's user-level permissions will also take effect. +If the project belongs to a user, the owner of the project has direct control over who has access to the project; if the project belongs to a group, the group's user-level permissions will take effect. -Every project also has a visibility level, which controls who has read access to that project's pages and repository. +Every project has a visibility level, which controls who has read access to that project's pages and repository. If a project is _Private_, the project's owner must explicitly grant access to specific users. An _Internal_ project is visible to any logged-in user, and a _Public_ project is visible to anyone. Note that this controls both `git fetch` access as well as access to the web UI for that project. @@ -86,10 +85,10 @@ This is a great way to connect your Git repositories and GitLab instance to the ==== Basic Usage The first thing you'll want to do with GitLab is create a new project. -This is accomplished by clicking the ``+'' icon on the toolbar. +You can do this by clicking on the "`+`" icon on the toolbar. You'll be asked for the project's name, which namespace it should belong to, and what its visibility level should be. -Most of what you specify here isn't permanent, and can be re-adjusted later through the settings interface. -Click ``Create Project'', and you're done. +Most of what you specify here isn't permanent, and can be changed later through the settings interface. +Click "`Create Project`", and you're done. Once the project exists, you'll probably want to connect it with a local Git repository. Each project is accessible over HTTPS or SSH, either of which can be used to configure a Git remote. @@ -113,14 +112,14 @@ Each project's home page shows recent activity, and links along the top will lea ==== Working Together -The simplest way of working together on a GitLab project is by giving another user direct push access to the Git repository. -You can add a user to a project by going to the ``Members'' section of that project's settings, and associating the new user with an access level (the different access levels are discussed a bit in <<_gitlab_groups_section>>). -By giving a user an access level of ``Developer'' or above, that user can push commits and branches directly to the repository with impunity. +The simplest way of working together on a GitLab project is by giving each user direct push access to the Git repository. +You can add a user to a project by going to the "`Members`" section of that project's settings, and associating the new user with an access level (the different access levels are discussed a bit in <<_gitlab_groups_section>>). +By giving a user an access level of "`Developer`" or above, that user can push commits and branches directly to the repository. Another, more decoupled way of collaboration is by using merge requests. This feature enables any user that can see a project to contribute to it in a controlled way. Users with direct access can simply create a branch, push commits to it, and open a merge request from their branch back into `master` or any other branch. -Users who don't have push permissions for a repository can ``fork'' it (create their own copy), push commits to _that_ copy, and open a merge request from their fork back to the main project. +Users who don't have push permissions for a repository can "`fork`" it to create their own copy, push commits to _their_ copy, and open a merge request from their fork back to the main project. This model allows the owner to be in full control of what goes into the repository and when, while allowing contributions from untrusted users. Merge requests and issues are the main units of long-lived discussion in GitLab. @@ -128,4 +127,4 @@ Each merge request allows a line-by-line discussion of the proposed change (whic Both can be assigned to users, or organized into milestones. This section is focused mainly on the Git-related features of GitLab, but as a mature project, it provides many other features to help your team work together, such as project wikis and system maintenance tools. -One benefit to GitLab is that, once the server is set up and running, you'll rarely need to tweak a configuration file or access the server via SSH; most administration and general usage can be accomplished through the in-browser interface. +One benefit to GitLab is that, once the server is set up and running, you'll rarely need to tweak a configuration file or access the server via SSH; most administration and general usage can be done through the in-browser interface. diff --git a/book/04-git-server/sections/gitweb.asc b/book/04-git-server/sections/gitweb.asc index b0c4572df..1565dc498 100644 --- a/book/04-git-server/sections/gitweb.asc +++ b/book/04-git-server/sections/gitweb.asc @@ -5,12 +5,12 @@ Now that you have basic read/write and read-only access to your project, you may Git comes with a CGI script called GitWeb that is sometimes used for this. [[gitweb]] -.The GitWeb web-based user interface. -image::images/git-instaweb.png[The GitWeb web-based user interface.] +.The GitWeb web-based user interface +image::images/git-instaweb.png[The GitWeb web-based user interface] If you want to check out what GitWeb would look like for your project, Git comes with a command to fire up a temporary instance if you have a lightweight web server on your system like `lighttpd` or `webrick`. On Linux machines, `lighttpd` is often installed, so you may be able to get it to run by typing `git instaweb` in your project directory. -If you're running a Mac, Leopard comes preinstalled with Ruby, so `webrick` may be your best bet. +If you're running macOS, Leopard comes preinstalled with Ruby, so `webrick` may be your best bet. To start `instaweb` with a non-lighttpd handler, you can run it with the `--httpd` option.(((git commands, instaweb))) [source,console] @@ -36,7 +36,7 @@ First, you need to get the Git source code, which GitWeb comes with, and generat [source,console] ---- -$ git clone git://git.kernel.org/pub/scm/git/git.git +$ git clone https://git.kernel.org/pub/scm/git/git.git $ cd git/ $ make GITWEB_PROJECTROOT="/srv/git" prefix=/usr gitweb SUBDIR gitweb diff --git a/book/04-git-server/sections/hosted.asc b/book/04-git-server/sections/hosted.asc index 6828f64e5..54eb79334 100644 --- a/book/04-git-server/sections/hosted.asc +++ b/book/04-git-server/sections/hosted.asc @@ -2,9 +2,9 @@ If you don't want to go through all of the work involved in setting up your own Git server, you have several options for hosting your Git projects on an external dedicated hosting site. Doing so offers a number of advantages: a hosting site is generally quick to set up and easy to start projects on, and no server maintenance or monitoring is involved. -Even if you set up and run your own server internally, you may still want to use a public hosting site for your open source code – it's generally easier for the open source community to find and help you with. +Even if you set up and run your own server internally, you may still want to use a public hosting site for your open source code -- it's generally easier for the open source community to find and help you with. These days, you have a huge number of hosting options to choose from, each with different advantages and disadvantages. -To see an up-to-date list, check out the GitHosting page on the main Git wiki at https://git.wiki.kernel.org/index.php/GitHosting[] +To see an up-to-date list, check out the GitHosting page on the main Git wiki at https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/GitHosting.html[^]. We'll cover using GitHub in detail in <>, as it is the largest Git host out there and you may need to interact with projects hosted on it in any case, but there are dozens more to choose from should you not want to set up your own Git server. diff --git a/book/04-git-server/sections/protocols.asc b/book/04-git-server/sections/protocols.asc index 946cf5ae3..ff226d1e6 100644 --- a/book/04-git-server/sections/protocols.asc +++ b/book/04-git-server/sections/protocols.asc @@ -7,7 +7,7 @@ Here we'll discuss what they are and in what basic circumstances you would want (((protocols, local))) The most basic is the _Local protocol_, in which the remote repository is in another directory on the same host. -This is often used if everyone on your team has access to a shared filesystem such as an NFS mount, or in the less likely case that everyone logs in to the same computer. +This is often used if everyone on your team has access to a shared filesystem such as an https://en.wikipedia.org/wiki/Network_File_System[NFS^] mount, or in the less likely case that everyone logs in to the same computer. The latter wouldn't be ideal, because all your code repository instances would reside on the same computer, making a catastrophic loss much more likely. If you have a shared mounted filesystem, then you can clone, push to, and pull from a local file-based repository. @@ -61,7 +61,7 @@ A local repository is fast only if you have fast access to the data. A repository on NFS is often slower than the repository over SSH on the same server, allowing Git to run off local disks on each system. Finally, this protocol does not protect the repository against accidental damage. -Every user has full shell access to the ``remote'' directory, and there is nothing preventing them from changing or removing internal Git files and corrupting the repository. +Every user has full shell access to the "`remote`" directory, and there is nothing preventing them from changing or removing internal Git files and corrupting the repository. ==== The HTTP Protocols @@ -82,7 +82,7 @@ Instead of having to set up different URLs for these things, you can now use a s If you try to push and the repository requires authentication (which it normally should), the server can prompt for a username and password. The same goes for read access. -In fact, for services like GitHub, the URL you use to view the repository online (for example, https://github.com/schacon/simplegit[]) is the same URL you can use to clone and, if you have access, push over. +In fact, for services like GitHub, the URL you use to view the repository online (for example, https://github.com/schacon/simplegit[^]) is the same URL you can use to clone and, if you have access, push over. ===== Dumb HTTP @@ -90,7 +90,7 @@ In fact, for services like GitHub, the URL you use to view the repository online If the server does not respond with a Git HTTP smart service, the Git client will try to fall back to the simpler _Dumb_ HTTP protocol. The Dumb protocol expects the bare Git repository to be served like normal files from the web server. The beauty of Dumb HTTP is the simplicity of setting it up. -Basically, all you have to do is put a bare Git repository under your HTTP document root and set up a specific `post-update` hook, and you're done (See <>). +Basically, all you have to do is put a bare Git repository under your HTTP document root and set up a specific `post-update` hook, and you're done (see <>). At that point, anyone who can access the web server under which you put the repository can also clone your repository. To allow read access to your repository over HTTP, do something like this: @@ -105,7 +105,7 @@ $ chmod a+x hooks/post-update That's all.(((hooks, post-update))) The `post-update` hook that comes with Git by default runs the appropriate command (`git update-server-info`) to make HTTP fetching and cloning work properly. -This command is run when you push to this repository (over SSH perhaps); then, other people can clone via something like +This command is run when you push to this repository (over SSH perhaps); then, other people can clone via something like: [source,console] ---- @@ -129,7 +129,7 @@ It is also a very fast and efficient protocol, similar to the SSH one. You can also serve your repositories read-only over HTTPS, which means you can encrypt the content transfer; or you can go so far as to make the clients use specific signed SSL certificates. -Another nice thing is that HTTPS are such commonly used protocols that corporate firewalls are often set up to allow traffic through these ports. +Another nice thing is that HTTP and HTTPS are such commonly used protocols that corporate firewalls are often set up to allow traffic through their ports. ===== The Cons @@ -181,7 +181,7 @@ If you want to allow anonymous read-only access to your projects and also want t (((protocols, git))) Finally, we have the Git protocol. -This is a special daemon that comes packaged with Git; it listens on a dedicated port (9418) that provides a service similar to the SSH protocol, but with absolutely no authentication. +This is a special daemon that comes packaged with Git; it listens on a dedicated port (9418) that provides a service similar to the SSH protocol, but with absolutely no authentication or cryptography. In order for a repository to be served over the Git protocol, you must create a `git-daemon-export-ok` file -- the daemon won't serve a repository without that file in it -- but, other than that, there is no security. Either the Git repository is available for everyone to clone, or it isn't. This means that there is generally no pushing over this protocol. @@ -196,9 +196,15 @@ It uses the same data-transfer mechanism as the SSH protocol but without the enc ===== The Cons -The downside of the Git protocol is the lack of authentication. -It's generally undesirable for the Git protocol to be the only access to your project. -Generally, you'll pair it with SSH or HTTPS access for the few developers who have push (write) access and have everyone else use `git://` for read-only access. +Due to the lack of TLS or other cryptography, cloning over `git://` might lead to an arbitrary code execution vulnerability, and should therefore be avoided unless you know what you are doing. + +* If you run `git clone git://example.com/project.git`, an attacker who controls e.g your router can modify the repo you just cloned, inserting malicious code into it. + If you then compile/run the code you just cloned, you will execute the malicious code. + Running `git clone http://example.com/project.git` should be avoided for the same reason. +* Running `git clone https://example.com/project.git` does not suffer from the same problem (unless the attacker can provide a TLS certificate for example.com). + Running `git clone git@example.com:project.git` only suffers from this problem if you accept a wrong SSH key fingerprint. + +It also has no authentication, i.e. anyone can clone the repo (although this is often exactly what you want). It's also probably the most difficult protocol to set up. It must run its own daemon, which requires `xinetd` or `systemd` configuration or the like, which isn't always a walk in the park. It also requires firewall access to port 9418, which isn't a standard port that corporate firewalls always allow. diff --git a/book/04-git-server/sections/setting-up-server.asc b/book/04-git-server/sections/setting-up-server.asc index 17fd9dbdb..bbb082956 100644 --- a/book/04-git-server/sections/setting-up-server.asc +++ b/book/04-git-server/sections/setting-up-server.asc @@ -67,7 +67,7 @@ If you're running it internally, and you set up DNS for `gitserver` to point to $ cd myproject $ git init $ git add . -$ git commit -m 'initial commit' +$ git commit -m 'Initial commit' $ git remote add origin git@gitserver:/srv/git/project.git $ git push origin master ---- @@ -79,7 +79,7 @@ At this point, the others can clone it down and push changes back up just as eas $ git clone git@gitserver:/srv/git/project.git $ cd project $ vim README -$ git commit -am 'fix for the README file' +$ git commit -am 'Fix for README file' $ git push origin master ---- @@ -89,13 +89,13 @@ You should note that currently all these users can also log into the server and If you want to restrict that, you will have to change the shell to something else in the `/etc/passwd` file. You can easily restrict the `git` user account to only Git-related activities with a limited shell tool called `git-shell` that comes with Git. -If you set this as the `git` user account's login shell, then that account can't have normal shell access to your server. -To use this, specify `git-shell` instead of bash or csh for that account's login shell. +If you set this as the `git` user account's login shell, then that account can't have normal shell access to your server. +To use this, specify `git-shell` instead of `bash` or `csh` for that account's login shell. To do so, you must first add the full pathname of the `git-shell` command to `/etc/shells` if it's not already there: [source,console] ---- -$ cat /etc/shells # see if `git-shell` is already in there. If not... +$ cat /etc/shells # see if git-shell is already in there. If not... $ which git-shell # make sure git-shell is installed on your system. $ sudo -e /etc/shells # and add the path to git-shell from last command ---- @@ -107,7 +107,7 @@ Now you can edit the shell for a user using `chsh -s `: $ sudo chsh git -s $(which git-shell) ---- -Now, the `git` user can only use the SSH connection to push and pull Git repositories and can't shell onto the machine. +Now, the `git` user can still use the SSH connection to push and pull Git repositories but can't shell onto the machine. If you try, you'll see a login rejection like this: [source,console] @@ -118,6 +118,31 @@ hint: ~/git-shell-commands should exist and have read and execute access. Connection to gitserver closed. ---- +At this point, users are still able to use SSH port forwarding to access any host the git server is able to reach. +If you want to prevent that, you can edit the `authorized_keys` file and prepend the following options to each key you'd like to restrict: + +[source,console] +---- +no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty +---- + +The result should look like this: + +[source,console] +---- +$ cat ~/.ssh/authorized_keys +no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa +AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4LojG6rs6h +PB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4kYjh6541N +YsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9EzSdfd8AcC +IicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myivO7TCUSBd +LQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPqdAv8JggJ +ICUvax2T9va5 gsg-keypair + +no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa +AAAAB3NzaC1yc2EAAAADAQABAAABAQDEwENNMomTboYI+LJieaAY16qiXiH3wuvENhBG... +---- + Now Git network commands will still work just fine but the users won't be able to get a shell. As the output states, you can also set up a directory in the `git` user's home directory that customizes the `git-shell` command a bit. For instance, you can restrict the Git commands that the server will accept or you can customize the message that users see if they try to SSH in like that. diff --git a/book/04-git-server/sections/smart-http.asc b/book/04-git-server/sections/smart-http.asc index 60bdd3097..753d34cd5 100644 --- a/book/04-git-server/sections/smart-http.asc +++ b/book/04-git-server/sections/smart-http.asc @@ -50,7 +50,7 @@ Finally you'll want to tell Apache to allow requests to `git-http-backend` and m ---- That will require you to create a `.htpasswd` file containing the passwords of all the valid users. -Here is an example of adding a ``schacon'' user to the file: +Here is an example of adding a "`schacon`" user to the file: [source,console] ---- @@ -68,5 +68,5 @@ You can do this with nearly any CGI-capable web server, so go with the one that [NOTE] ==== -For more information on configuring authentication in Apache, check out the Apache docs here: https://httpd.apache.org/docs/current/howto/auth.html[] +For more information on configuring authentication in Apache, check out the Apache docs here: https://httpd.apache.org/docs/current/howto/auth.html[^]. ==== diff --git a/book/05-distributed-git/sections/contributing.asc b/book/05-distributed-git/sections/contributing.asc index 56a13aa24..2c6b08516 100644 --- a/book/05-distributed-git/sections/contributing.asc +++ b/book/05-distributed-git/sections/contributing.asc @@ -41,8 +41,8 @@ The Git project provides a document that lays out a number of good tips for crea First, your submissions should not contain any whitespace errors. Git provides an easy way to check for this -- before you commit, run `git diff --check`, which identifies possible whitespace errors and lists them for you. -.Output of `git diff --check`. -image::images/git-diff-check.png[Output of `git diff --check`.] +.Output of `git diff --check` +image::images/git-diff-check.png[Output of `git diff --check`] If you run that command before committing, you can tell if you're about to commit whitespace issues that may annoy other developers. @@ -60,7 +60,7 @@ Getting in the habit of creating quality commit messages makes using and collabo As a general rule, your messages should start with a single line that's no more than about 50 characters and that describes the changeset concisely, followed by a blank line, followed by a more detailed explanation. The Git project requires that the more detailed explanation include your motivation for the change and contrast its implementation with previous behavior -- this is a good guideline to follow. Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug." -Here is a https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[template originally written by Tim Pope]: +Here is a template you can follow, which we've lightly adapted from one https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[originally written by Tim Pope^]: [source,text] ---- @@ -70,7 +70,7 @@ More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit -the body entirely); tools like rebase can get confused if you run the +the body entirely); tools like rebase will confuse you if you run the two together. Write your commit message in the imperative: "Fix bug" and not "Fixed bug" @@ -103,14 +103,14 @@ In short, do as we say, not as we do. (((contributing, private small team))) The simplest setup you're likely to encounter is a private project with one or two other developers. -``Private,'' in this context, means closed-source -- not accessible to the outside world. +"`Private,`" in this context, means closed-source -- not accessible to the outside world. You and the other developers all have push access to the repository. In this environment, you can follow a workflow similar to what you might do when using Subversion or another centralized system. You still get the advantages of things like offline committing and vastly simpler branching and merging, but the workflow can be very similar; the main difference is that merges happen client-side rather than on the server at commit time. Let's see what it might look like when two developers start to work together with a shared repository. The first developer, John, clones the repository, makes a change, and commits locally. -(The protocol messages have been replaced with `...` in these examples to shorten them somewhat.) +The protocol messages have been replaced with `...` in these examples to shorten them somewhat. [source,console] ---- @@ -120,8 +120,8 @@ Cloning into 'simplegit'... ... $ cd simplegit/ $ vim lib/simplegit.rb -$ git commit -am 'remove invalid default value' -[master 738ee87] remove invalid default value +$ git commit -am 'Remove invalid default value' +[master 738ee87] Remove invalid default value 1 files changed, 1 insertions(+), 1 deletions(-) ---- @@ -135,8 +135,8 @@ Cloning into 'simplegit'... ... $ cd simplegit/ $ vim TODO -$ git commit -am 'add reset task' -[master fbff5bc] add reset task +$ git commit -am 'Add reset task' +[master fbff5bc] Add reset task 1 files changed, 1 insertions(+), 0 deletions(-) ---- @@ -154,7 +154,7 @@ To jessica@githost:simplegit.git The last line of the output above shows a useful return message from the push operation. The basic format is `.. fromref -> toref`, where `oldref` means the old reference, `newref` means the new reference, `fromref` is the name of the local reference being pushed, and `toref` is the name of the remote reference being updated. You'll see similar output like this below in the discussions, so having a basic idea of the meaning will help in understanding the various states of the repositories. -More details are available in the documentation for https://git-scm.com/docs/git-push[git-push]. +More details are available in the documentation for https://git-scm.com/docs/git-push[git-push^]. Continuing with this example, shortly afterwards, John makes some changes, commits them to his local repository, and tries to push them to the same server: @@ -184,8 +184,8 @@ From john@githost:simplegit At this point, John's local repository looks something like this: -.John's divergent history. -image::images/small-team-1.png[John's divergent history.] +.John's divergent history +image::images/small-team-1.png[John's divergent history] Now John can merge Jessica's work that he fetched into his own local work: @@ -199,8 +199,8 @@ Merge made by the 'recursive' strategy. As long as that local merge goes smoothly, John's updated history will now look like this: -.John's repository after merging `origin/master`. -image::images/small-team-2.png[John's repository after merging `origin/master`.] +.John's repository after merging `origin/master` +image::images/small-team-2.png[John's repository after merging `origin/master`] At this point, John might want to test this new code to make sure none of Jessica's work affects any of his and, as long as everything seems fine, he can finally push the new merged work up to the server: @@ -214,14 +214,14 @@ To john@githost:simplegit.git In the end, John's commit history will look like this: -.John's history after pushing to the `origin` server. -image::images/small-team-3.png[John's history after pushing to the `origin` server.] +.John's history after pushing to the `origin` server +image::images/small-team-3.png[John's history after pushing to the `origin` server] In the meantime, Jessica has created a new topic branch called `issue54`, and made three commits to that branch. She hasn't fetched John's changes yet, so her commit history looks like this: -.Jessica's topic branch. -image::images/small-team-4.png[Jessica's topic branch.] +.Jessica's topic branch +image::images/small-team-4.png[Jessica's topic branch] Suddenly, Jessica learns that John has pushed some new work to the server and she wants to take a look at it, so she can fetch all new content from the server that she does not yet have with: @@ -237,8 +237,8 @@ From jessica@githost:simplegit That pulls down the work John has pushed up in the meantime. Jessica's history now looks like this: -.Jessica's history after fetching John's changes. -image::images/small-team-5.png[Jessica's history after fetching John's changes.] +.Jessica's history after fetching John's changes +image::images/small-team-5.png[Jessica's history after fetching John's changes] Jessica thinks her topic branch is ready, but she wants to know what part of John's fetched work she has to merge into her work so that she can push. She runs `git log` to find out: @@ -250,18 +250,18 @@ commit 738ee872852dfaa9d6634e0dea7a324040193016 Author: John Smith Date: Fri May 29 16:01:27 2009 -0700 - remove invalid default value + Remove invalid default value ---- -The `issue54..origin/master` syntax is a log filter that asks Git to display only those commits that are on the latter branch (in this case `origin/master`) that are not on the first branch (in this case `issue54`). +The `issue54..origin/master` syntax is a log filter that asks Git to display only those commits that are on the latter branch (in this case `origin/master`) and that are not on the first branch (in this case `issue54`). We'll go over this syntax in detail in <>. From the above output, we can see that there is a single commit that John has made that Jessica has not merged into her local work. If she merges `origin/master`, that is the single commit that will modify her local work. -Now, Jessica can merge her topic work into her master branch, merge John's work (`origin/master`) into her `master` branch, and then push back to the server again. +Now, Jessica can merge her topic work into her `master` branch, merge John's work (`origin/master`) into her `master` branch, and then push back to the server again. -First (having committed all of the work on her `issue54` topic branch), Jessica switches back to her master branch in preparation for integrating all this work: +First (having committed all of the work on her `issue54` topic branch), Jessica switches back to her `master` branch in preparation for integrating all this work: [source,console] ---- @@ -298,8 +298,8 @@ Merge made by the 'recursive' strategy. Everything merges cleanly, and Jessica's history now looks like this: -.Jessica's history after merging John's changes. -image::images/small-team-6.png[Jessica's history after merging John's changes.] +.Jessica's history after merging John's changes +image::images/small-team-6.png[Jessica's history after merging John's changes] Now `origin/master` is reachable from Jessica's `master` branch, so she should be able to successfully push (assuming John hasn't pushed even more changes in the meantime): @@ -313,16 +313,16 @@ To jessica@githost:simplegit.git Each developer has committed a few times and merged each other's work successfully. -.Jessica's history after pushing all changes back to the server. -image::images/small-team-7.png[Jessica's history after pushing all changes back to the server.] +.Jessica's history after pushing all changes back to the server +image::images/small-team-7.png[Jessica's history after pushing all changes back to the server] That is one of the simplest workflows. You work for a while (generally in a topic branch), and merge that work into your `master` branch when it's ready to be integrated. When you want to share that work, you fetch and merge your `master` from `origin/master` if it has changed, and finally push to the `master` branch on the server. The general sequence is something like this: -.General sequence of events for a simple multiple-developer Git workflow. -image::images/small-team-flow.png[General sequence of events for a simple multiple-developer Git workflow.] +.General sequence of events for a simple multiple-developer Git workflow +image::images/small-team-flow.png[General sequence of events for a simple multiple-developer Git workflow] ==== Private Managed Team @@ -330,7 +330,7 @@ image::images/small-team-flow.png[General sequence of events for a simple multip In this next scenario, you'll look at contributor roles in a larger private group. You'll learn how to work in an environment where small groups collaborate on features, after which those team-based contributions are integrated by another party. -Let's say that John and Jessica are working together on one feature (call this ``featureA''), while Jessica and a third developer, Josie, are working on a second (say, ``featureB''). +Let's say that John and Jessica are working together on one feature (call this "`featureA`"), while Jessica and a third developer, Josie, are working on a second (say, "`featureB`"). In this case, the company is using a type of integration-manager workflow where the work of the individual groups is integrated only by certain engineers, and the `master` branch of the main repo can be updated only by those engineers. In this scenario, all work is done in team-based branches and pulled together by the integrators later. @@ -344,8 +344,8 @@ She creates a new branch for the feature and does some work on it there: $ git checkout -b featureA Switched to a new branch 'featureA' $ vim lib/simplegit.rb -$ git commit -am 'add limit to log function' -[featureA 3300904] add limit to log function +$ git commit -am 'Add limit to log function' +[featureA 3300904] Add limit to log function 1 files changed, 1 insertions(+), 1 deletions(-) ---- @@ -377,21 +377,21 @@ Now, Jessica makes a couple of commits on the `featureB` branch: [source,console] ---- $ vim lib/simplegit.rb -$ git commit -am 'made the ls-tree function recursive' -[featureB e5b0fdc] made the ls-tree function recursive +$ git commit -am 'Make ls-tree function recursive' +[featureB e5b0fdc] Make ls-tree function recursive 1 files changed, 1 insertions(+), 1 deletions(-) $ vim lib/simplegit.rb -$ git commit -am 'add ls-files' -[featureB 8512791] add ls-files +$ git commit -am 'Add ls-files' +[featureB 8512791] Add ls-files 1 files changed, 5 insertions(+), 0 deletions(-) ---- Jessica's repository now looks like this: -.Jessica's initial commit history. -image::images/managed-team-1.png[Jessica's initial commit history.] +.Jessica's initial commit history +image::images/managed-team-1.png[Jessica's initial commit history] -She's ready to push her work, but gets an email from Josie that a branch with some initial ``featureB'' work on it was already pushed to the server as the `featureBee` branch. +She's ready to push her work, but gets an email from Josie that a branch with some initial "`featureB`" work on it was already pushed to the server as the `featureBee` branch. Jessica needs to merge those changes with her own before she can push her work to the server. Jessica first fetches Josie's changes with `git fetch`: @@ -414,7 +414,7 @@ Merge made by the 'recursive' strategy. 1 files changed, 4 insertions(+), 0 deletions(-) ---- -At this point, Jessica wants to push all of this merged ``featureB'' work back to the server, but she doesn't want to simply push her own `featureB` branch. +At this point, Jessica wants to push all of this merged "`featureB`" work back to the server, but she doesn't want to simply push her own `featureB` branch. Rather, since Josie has already started an upstream `featureBee` branch, Jessica wants to push to _that_ branch, which she does with: [source,console] @@ -449,7 +449,7 @@ commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6 Author: John Smith Date: Fri May 29 19:57:33 2009 -0700 - changed log output to 30 from 25 + Increase log output to 30 from 25 ---- If Jessica likes what she sees, she can merge John's new work into her local `featureA` branch with: @@ -465,12 +465,12 @@ Fast forward 1 files changed, 9 insertions(+), 1 deletions(-) ---- -Finally, Jessica might want to make a couple minor changes to all that merged content, so she is free to make those changes, commit them to her local `featureA` branch, and push the end result back to the server. +Finally, Jessica might want to make a couple minor changes to all that merged content, so she is free to make those changes, commit them to her local `featureA` branch, and push the end result back to the server: [source,console] ---- -$ git commit -am 'small tweak' -[featureA 774b3ed] small tweak +$ git commit -am 'Add small tweak to merged content' +[featureA 774b3ed] Add small tweak to merged content 1 files changed, 1 insertions(+), 1 deletions(-) $ git push ... @@ -480,21 +480,21 @@ To jessica@githost:simplegit.git Jessica's commit history now looks something like this: -.Jessica's history after committing on a feature branch. -image::images/managed-team-2.png[Jessica's history after committing on a feature branch.] +.Jessica's history after committing on a feature branch +image::images/managed-team-2.png[Jessica's history after committing on a feature branch] At some point, Jessica, Josie, and John inform the integrators that the `featureA` and `featureBee` branches on the server are ready for integration into the mainline. After the integrators merge these branches into the mainline, a fetch will bring down the new merge commit, making the history look like this: -.Jessica's history after merging both her topic branches. -image::images/managed-team-3.png[Jessica's history after merging both her topic branches.] +.Jessica's history after merging both her topic branches +image::images/managed-team-3.png[Jessica's history after merging both her topic branches] Many groups switch to Git because of this ability to have multiple teams working in parallel, merging the different lines of work late in the process. The ability of smaller subgroups of a team to collaborate via remote branches without necessarily having to involve or impede the entire team is a huge benefit of Git. The sequence for the workflow you saw here is something like this: -.Basic sequence of this managed-team workflow. -image::images/managed-team-flow.png[Basic sequence of this managed-team workflow.] +.Basic sequence of this managed-team workflow +image::images/managed-team-flow.png[Basic sequence of this managed-team workflow] [[_public_project]] ==== Forked Public Project @@ -525,7 +525,7 @@ $ git commit You may want to use `rebase -i` to squash your work down to a single commit, or rearrange the work in the commits to make the patch easier for the maintainer to review -- see <> for more information about interactive rebasing. ==== -When your branch work is finished and you're ready to contribute it back to the maintainers, go to the original project page and click the ``Fork'' button, creating your own writable fork of the project. +When your branch work is finished and you're ready to contribute it back to the maintainers, go to the original project page and click the "`Fork`" button, creating your own writable fork of the project. You then need to add this repository URL as a new remote of your local repository; in this example, let's call it `myfork`: [source,console] @@ -534,8 +534,8 @@ $ git remote add myfork ---- You then need to push your new work to this repository. -It's easiest to push the topic branch you're working on to your forked repository, rather than merging that work into your master branch and pushing that. -The reason is that if your work isn't accepted or is cherry-picked, you don't have to rewind your master branch (the Git `cherry-pick` operation is covered in more detail in <>). +It's easiest to push the topic branch you're working on to your forked repository, rather than merging that work into your `master` branch and pushing that. +The reason is that if your work isn't accepted or is cherry-picked, you don't have to rewind your `master` branch (the Git `cherry-pick` operation is covered in more detail in <>). If the maintainers `merge`, `rebase`, or `cherry-pick` your work, you'll eventually get it back via pulling from their repository anyhow. In any event, you can push your work with: @@ -547,7 +547,7 @@ $ git push -u myfork featureA (((git commands, request-pull))) Once your work has been pushed to your fork of the repository, you need to notify the maintainers of the original project that you have work you'd like them to merge. -This is often called a _pull request_, and you typically generate such a request either via the website -- GitHub has its own ``Pull Request'' mechanism that we'll go over in <> -- or you can run the `git request-pull` command and email the subsequent output to the project maintainer manually. +This is often called a _pull request_, and you typically generate such a request either via the website -- GitHub has its own "`Pull Request`" mechanism that we'll go over in <> -- or you can run the `git request-pull` command and email the subsequent output to the project maintainer manually. The `git request-pull` command takes the base branch into which you want your topic branch pulled and the Git repository URL you want them to pull from, and produces a summary of all the changes you're asking to be pulled. For instance, if Jessica wants to send John a pull request, and she's done two commits on the topic branch she just pushed, she can run this: @@ -557,15 +557,15 @@ For instance, if Jessica wants to send John a pull request, and she's done two c $ git request-pull origin/master myfork The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40: Jessica Smith (1): - added a new function + Create new function are available in the git repository at: - git://githost/simplegit.git featureA + https://githost/simplegit.git featureA Jessica Smith (2): - add limit to log function - change log output to 30 from 25 + Add limit to log function + Increase log output to 30 from 25 lib/simplegit.rb | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) @@ -590,8 +590,8 @@ $ git fetch origin Now, each of your topics is contained within a silo -- similar to a patch queue -- that you can rewrite, rebase, and modify without the topics interfering or interdepending on each other, like so: -.Initial commit history with `featureB` work. -image::images/public-small-1.png[Initial commit history with `featureB` work.] +.Initial commit history with `featureB` work +image::images/public-small-1.png[Initial commit history with `featureB` work] Let's say the project maintainer has pulled in a bunch of other patches and tried your first branch, but it no longer cleanly merges. In this case, you can try to rebase that branch on top of `origin/master`, resolve the conflicts for the maintainer, and then resubmit your changes: @@ -606,8 +606,8 @@ $ git push -f myfork featureA This rewrites your history to now look like <>. [[psp_b]] -.Commit history after `featureA` work. -image::images/public-small-2.png[Commit history after `featureA` work.] +.Commit history after `featureA` work +image::images/public-small-2.png[Commit history after `featureA` work] Because you rebased the branch, you have to specify the `-f` to your push command in order to be able to replace the `featureA` branch on the server with a commit that isn't a descendant of it. An alternative would be to push this new work to a different branch on the server (perhaps called `featureAv2`). @@ -632,8 +632,8 @@ Also the `--no-commit` option can be useful to delay the merge commit in case of At this point, you can notify the maintainer that you've made the requested changes, and that they can find those changes in your `featureBv2` branch. -.Commit history after `featureBv2` work. -image::images/public-small-3.png[Commit history after `featureBv2` work.] +.Commit history after `featureBv2` work +image::images/public-small-3.png[Commit history after `featureBv2` work] [[_project_over_email]] ==== Public Project over Email @@ -664,7 +664,7 @@ The nice thing about this is that applying a patch from an email generated with ---- $ git format-patch -M origin/master 0001-add-limit-to-log-function.patch -0002-changed-log-output-to-30-from-25.patch +0002-increase-log-output-to-30-from-25.patch ---- The `format-patch` command prints out the names of the patch files it creates. @@ -677,7 +677,7 @@ $ cat 0001-add-limit-to-log-function.patch From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001 From: Jessica Smith Date: Sun, 6 Apr 2008 10:17:23 -0700 -Subject: [PATCH 1/2] add limit to log function +Subject: [PATCH 1/2] Add limit to log function Limit log functionality to the first 20 @@ -706,7 +706,7 @@ You can also edit these patch files to add more information for the email list t If you add text between the `---` line and the beginning of the patch (the `diff --git` line), the developers can read it, but that content is ignored by the patching process. To email this to a mailing list, you can either paste the file into your email program or send it via a command-line program. -Pasting the text often causes formatting issues, especially with ``smarter'' clients that don't preserve newlines and other whitespace appropriately. +Pasting the text often causes formatting issues, especially with "`smarter`" clients that don't preserve newlines and other whitespace appropriately. Luckily, Git provides a tool to help you send properly formatted patches via IMAP, which may be easier for you. We'll demonstrate how to send a patch via Gmail, which happens to be the email agent we know best; you can read detailed instructions for a number of mail programs at the end of the aforementioned `Documentation/SubmittingPatches` file in the Git source code. @@ -757,8 +757,8 @@ After this is done, you can use `git send-email` to send your patches: [source,console] ---- $ git send-email *.patch -0001-added-limit-to-log-function.patch -0002-changed-log-output-to-30-from-25.patch +0001-add-limit-to-log-function.patch +0002-increase-log-output-to-30-from-25.patch Who should the emails appear to be from? [Jessica Smith ] Emails will be sent from: Jessica Smith Who should the emails be sent to? jessica@example.com @@ -775,7 +775,7 @@ OK. Log says: Sendmail: /usr/sbin/sendmail -i jessica@example.com From: Jessica Smith To: jessica@example.com -Subject: [PATCH 1/2] added limit to log function +Subject: [PATCH 1/2] Add limit to log function Date: Sat, 30 May 2009 13:29:15 -0700 Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com> X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty @@ -785,8 +785,18 @@ References: Result: OK ---- +[TIP] +==== +For help on configuring your system and email, more tips and tricks, and a sandbox to send a trial patch via email, go to https://git-send-email.io[git-send-email.io^]. +==== + ==== Summary -This section has covered a number of common workflows for dealing with several very different types of Git projects you're likely to encounter, and introduced a couple of new tools to help you manage this process. +In this section, we covered multiple workflows, and talked about the differences between working as part of a small team on closed-source projects vs contributing to a big public project. +You know to check for white-space errors before committing, and can write a great commit message. +You learned how to format patches, and e-mail them to a developer mailing list. +Dealing with merges was also covered in the context of the different workflows. +You are now well prepared to collaborate on any project. + Next, you'll see how to work the other side of the coin: maintaining a Git project. You'll learn how to be a benevolent dictator or integration manager. diff --git a/book/05-distributed-git/sections/distributed-workflows.asc b/book/05-distributed-git/sections/distributed-workflows.asc index 124fbad77..b61289dc1 100644 --- a/book/05-distributed-git/sections/distributed-workflows.asc +++ b/book/05-distributed-git/sections/distributed-workflows.asc @@ -14,8 +14,8 @@ In centralized systems, there is generally a single collaboration model -- the c One central hub, or _repository_, can accept code, and everyone synchronizes their work with it. A number of developers are nodes -- consumers of that hub -- and synchronize with that centralized location. -.Centralized workflow. -image::images/centralized_workflow.png[Centralized workflow.] +.Centralized workflow +image::images/centralized_workflow.png[Centralized workflow] This means that if two developers clone from the hub and both make changes, the first developer to push their changes back up can do so with no problems. The second developer must merge in the first one's work before pushing changes up, so as not to overwrite the first developer's changes. @@ -38,7 +38,7 @@ With Git's branching model, it's possible for hundreds of developers to successf (((workflows, integration manager))) Because Git allows you to have multiple remote repositories, it's possible to have a workflow where each developer has write access to their own public repository and read access to everyone else's. -This scenario often includes a canonical repository that represents the ``official'' project. +This scenario often includes a canonical repository that represents the "`official`" project. To contribute to that project, you create your own public clone of the project and push your changes to it. Then, you can send a request to the maintainer of the main project to pull in your changes. The maintainer can then add your repository as a remote, test your changes locally, merge them into their branch, and push back to their repository. @@ -52,8 +52,8 @@ The process works as follows (see <>): 6. The maintainer pushes merged changes to the main repository. [[wfdiag_b]] -.Integration-manager workflow. -image::images/integration-manager.png[Integration-manager workflow.] +.Integration-manager workflow +image::images/integration-manager.png[Integration-manager workflow] (((forking))) This is a very common workflow with hub-based tools like GitHub or GitLab, where it's easy to fork a project and push your changes into your fork for everyone to see. @@ -67,7 +67,7 @@ This is a variant of a multiple-repository workflow. It's generally used by huge projects with hundreds of collaborators; one famous example is the Linux kernel. Various integration managers are in charge of certain parts of the repository; they're called _lieutenants_. All the lieutenants have one integration manager known as the benevolent dictator. -The benevolent dictator pushes from his directory to a reference repository from which all the collaborators need to pull. +The benevolent dictator pushes from their directory to a reference repository from which all the collaborators need to pull. The process works like this (see <>): 1. Regular developers work on their topic branch and rebase their work on top of `master`. @@ -77,12 +77,24 @@ The process works like this (see <>): 4. Finally, the dictator pushes that `master` branch to the reference repository so the other developers can rebase on it. [[wfdiag_c]] -.Benevolent dictator workflow. -image::images/benevolent-dictator.png[Benevolent dictator workflow.] +.Benevolent dictator workflow +image::images/benevolent-dictator.png[Benevolent dictator workflow] This kind of workflow isn't common, but can be useful in very big projects, or in highly hierarchical environments. It allows the project leader (the dictator) to delegate much of the work and collect large subsets of code at multiple points before integrating them. +[[_patterns_for_managing_source_code_branches]] +==== Patterns for Managing Source Code Branches + +[NOTE] +==== +Martin Fowler has made a guide "Patterns for Managing Source Code Branches". +This guide covers all the common Git workflows, and explains how/when to use them. +There's also a section comparing high and low integration frequencies. + +https://martinfowler.com/articles/branching-patterns.html[^] +==== + ==== Workflows Summary These are some commonly used workflows that are possible with a distributed system like Git, but you can see that many variations are possible to suit your particular real-world workflow. diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 44cab8061..c377bb68d 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -35,7 +35,7 @@ Now you're ready to add the contributed work that you received into this topic b If you receive a patch over email that you need to integrate into your project, you need to apply the patch in your topic branch to evaluate it. There are two ways to apply an emailed patch: with `git apply` or with `git am`. -===== Applying a Patch with apply +===== Applying a Patch with `apply` (((git commands, apply))) If you received the patch from someone who generated it with `git diff` or some variation of the Unix `diff` command (which is not recommended; see the next section), you can apply it with the `git apply` command. @@ -49,7 +49,7 @@ $ git apply /tmp/patch-ruby-client.patch This modifies the files in your working directory. It's almost identical to running a `patch -p1` command to apply the patch, although it's more paranoid and accepts fewer fuzzy matches than patch. It also handles file adds, deletes, and renames if they're described in the `git diff` format, which `patch` won't do. -Finally, `git apply` is an ``apply all or abort all'' model where either everything is applied or nothing is, whereas `patch` can partially apply patchfiles, leaving your working directory in a weird state. +Finally, `git apply` is an "`apply all or abort all`" model where either everything is applied or nothing is, whereas `patch` can partially apply patchfiles, leaving your working directory in a weird state. `git apply` is overall much more conservative than `patch`. It won't create a commit for you -- after running it, you must stage and commit the changes introduced manually. @@ -57,7 +57,7 @@ You can also use `git apply` to see if a patch applies cleanly before you try ac [source,console] ---- -$ git apply --check 0001-seeing-if-this-helps-the-gem.patch +$ git apply --check 0001-see-if-this-helps-the-gem.patch error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply ---- @@ -82,7 +82,7 @@ It looks something like this: From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001 From: Jessica Smith Date: Sun, 6 Apr 2008 10:17:23 -0700 -Subject: [PATCH 1/2] add limit to log function +Subject: [PATCH 1/2] Add limit to log function Limit log functionality to the first 20 ---- @@ -96,7 +96,7 @@ However, if someone uploaded a patch file generated via `git format-patch` to a [source,console] ---- $ git am 0001-limit-log-function.patch -Applying: add limit to log function +Applying: Add limit to log function ---- You can see that it applied cleanly and automatically created the new commit for you. @@ -112,7 +112,7 @@ AuthorDate: Sun Apr 6 10:17:23 2008 -0700 Commit: Scott Chacon CommitDate: Thu Apr 9 09:19:06 2009 -0700 - add limit to log function + Add limit to log function Limit log functionality to the first 20 ---- @@ -126,8 +126,8 @@ In that case, the `git am` process will fail and ask you what you want to do: [source,console] ---- -$ git am 0001-seeing-if-this-helps-the-gem.patch -Applying: seeing if this helps the gem +$ git am 0001-see-if-this-helps-the-gem.patch +Applying: See if this helps the gem error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply Patch failed at 0001. @@ -144,7 +144,7 @@ You solve this issue much the same way -- edit the file to resolve the conflict, $ (fix the file) $ git add ticgit.gemspec $ git am --resolved -Applying: seeing if this helps the gem +Applying: See if this helps the gem ---- If you want Git to try a bit more intelligently to resolve the conflict, you can pass a `-3` option to it, which makes Git attempt a three-way merge. @@ -153,8 +153,8 @@ If you do have that commit -- if the patch was based on a public commit -- then [source,console] ---- -$ git am -3 0001-seeing-if-this-helps-the-gem.patch -Applying: seeing if this helps the gem +$ git am -3 0001-see-if-this-helps-the-gem.patch +Applying: See if this helps the gem error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply Using index info to reconstruct a base tree... @@ -172,7 +172,7 @@ If you're applying a number of patches from an mbox, you can also run the `am` c $ git am -3 -i mbox Commit Body is: -------------------------- -seeing if this helps the gem +See if this helps the gem -------------------------- Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all ---- @@ -191,7 +191,7 @@ For instance, if Jessica sends you an email saying that she has a great new feat [source,console] ---- -$ git remote add jessica git://github.com/jessica/myproject.git +$ git remote add jessica https://github.com/jessica/myproject.git $ git fetch jessica $ git checkout -b rubyclient jessica/ruby-client ---- @@ -225,8 +225,8 @@ Now you have a topic branch that contains contributed work. At this point, you can determine what you'd like to do with it. This section revisits a couple of commands so you can see how you can use them to review exactly what you'll be introducing if you merge this into your main branch. -It's often helpful to get a review of all the commits that are in this branch but that aren't in your master branch. -You can exclude commits in the master branch by adding the `--not` option before the branch name. +It's often helpful to get a review of all the commits that are in this branch but that aren't in your `master` branch. +You can exclude commits in the `master` branch by adding the `--not` option before the branch name. This does the same thing as the `master..contrib` format that we used earlier. For example, if your contributor sends you two patches and you create a branch called `contrib` and applied those patches there, you can run this: @@ -237,13 +237,13 @@ commit 5b6235bd297351589efc4d73316f0a68d484f118 Author: Scott Chacon Date: Fri Oct 24 09:53:59 2008 -0700 - seeing if this helps the gem + See if this helps the gem commit 7482e0d16d04bea79d0dba8988cc78df655f16a0 Author: Scott Chacon Date: Mon Oct 22 19:38:36 2008 -0700 - updated the gemspec to hopefully work better + Update gemspec to hopefully work better ---- To see what changes each commit introduces, remember that you can pass the `-p` option to `git log` and it will append the diff introduced to each commit. @@ -263,8 +263,8 @@ For example, if you've added a line in a file on the `master` branch, a direct c If `master` is a direct ancestor of your topic branch, this isn't a problem; but if the two histories have diverged, the diff will look like you're adding all the new stuff in your topic branch and removing everything unique to the `master` branch. -What you really want to see are the changes added to the topic branch -- the work you'll introduce if you merge this branch with master. -You do that by having Git compare the last commit on your topic branch with the first common ancestor it has with the master branch. +What you really want to see are the changes added to the topic branch -- the work you'll introduce if you merge this branch with `master`. +You do that by having Git compare the last commit on your topic branch with the first common ancestor it has with the `master` branch. Technically, you can do that by explicitly figuring out the common ancestor and then running your diff on it: @@ -290,7 +290,7 @@ In the context of the `git diff` command, you can put three periods after anothe $ git diff master...contrib ---- -This command shows you only the work your current topic branch has introduced since its common ancestor with master. +This command shows you only the work your current topic branch has introduced since its common ancestor with `master`. That is a very useful syntax to remember. ==== Integrating Contributed Work @@ -310,12 +310,12 @@ When you have work in a topic branch that you think you've completed, or work th For instance, if we have a repository with work in two branches named `ruby_client` and `php_client` that looks like <>, and we merge `ruby_client` followed by `php_client`, your history will end up looking like <>. [[merwf_a]] -.History with several topic branches. -image::images/merging-workflows-1.png[History with several topic branches.] +.History with several topic branches +image::images/merging-workflows-1.png[History with several topic branches] [[merwf_b]] -.After a topic branch merge. -image::images/merging-workflows-2.png[After a topic branch merge.] +.After a topic branch merge +image::images/merging-workflows-2.png[After a topic branch merge] That is probably the simplest workflow, but it can possibly be problematic if you're dealing with larger or more stable projects where you want to be really careful about what you introduce. @@ -325,16 +325,16 @@ You regularly push both of these branches to the public repository. Each time you have a new topic branch to merge in (<>), you merge it into `develop` (<>); then, when you tag a release, you fast-forward `master` to wherever the now-stable `develop` branch is (<>). [[merwf_c]] -.Before a topic branch merge. -image::images/merging-workflows-3.png[Before a topic branch merge.] +.Before a topic branch merge +image::images/merging-workflows-3.png[Before a topic branch merge] [[merwf_d]] -.After a topic branch merge. -image::images/merging-workflows-4.png[After a topic branch merge.] +.After a topic branch merge +image::images/merging-workflows-4.png[After a topic branch merge] [[merwf_e]] -.After a project release. -image::images/merging-workflows-5.png[After a topic branch release.] +.After a project release +image::images/merging-workflows-5.png[After a project release] This way, when people clone your project's repository, they can either check out `master` to build the latest stable version and keep up to date on that easily, or they can check out `develop`, which is the more cutting-edge content. You can also extend this concept by having an `integrate` branch where all the work is merged together. @@ -343,35 +343,35 @@ Then, when the codebase on that branch is stable and passes tests, you merge it ===== Large-Merging Workflows (((workflows, "merging (large)"))) -The Git project has four long-running branches: `master`, `next`, and `pu` (proposed updates) for new work, and `maint` for maintenance backports. +The Git project has four long-running branches: `master`, `next`, and `seen` (formerly 'pu' -- proposed updates) for new work, and `maint` for maintenance backports. When new work is introduced by contributors, it's collected into topic branches in the maintainer's repository in a manner similar to what we've described (see <>). At this point, the topics are evaluated to determine whether they're safe and ready for consumption or whether they need more work. If they're safe, they're merged into `next`, and that branch is pushed up so everyone can try the topics integrated together. [[merwf_f]] -.Managing a complex series of parallel contributed topic branches. -image::images/large-merges-1.png[Managing a complex series of parallel contributed topic branches.] +.Managing a complex series of parallel contributed topic branches +image::images/large-merges-1.png[Managing a complex series of parallel contributed topic branches] -If the topics still need work, they're merged into `pu` instead. +If the topics still need work, they're merged into `seen` instead. When it's determined that they're totally stable, the topics are re-merged into `master`. -The `next` and `pu` branches are then rebuilt from the `master`. -This means `master` almost always moves forward, `next` is rebased occasionally, and `pu` is rebased even more often: +The `next` and `seen` branches are then rebuilt from the `master`. +This means `master` almost always moves forward, `next` is rebased occasionally, and `seen` is rebased even more often: -.Merging contributed topic branches into long-term integration branches. -image::images/large-merges-2.png[Merging contributed topic branches into long-term integration branches.] +.Merging contributed topic branches into long-term integration branches +image::images/large-merges-2.png[Merging contributed topic branches into long-term integration branches] When a topic branch has finally been merged into `master`, it's removed from the repository. The Git project also has a `maint` branch that is forked off from the last release to provide backported patches in case a maintenance release is required. Thus, when you clone the Git repository, you have four branches that you can check out to evaluate the project in different stages of development, depending on how cutting edge you want to be or how you want to contribute; and the maintainer has a structured workflow to help them vet new contributions. The Git project's workflow is specialized. -To clearly understand this you could check out the https://github.com/git/git/blob/master/Documentation/howto/maintain-git.txt[Git Maintainer's guide]. +To clearly understand this you could check out the https://github.com/git/git/blob/master/Documentation/howto/maintain-git.txt[Git Maintainer's guide^]. [[_rebase_cherry_pick]] ===== Rebasing and Cherry-Picking Workflows (((workflows, rebasing and cherry-picking))) -Other maintainers prefer to rebase or cherry-pick contributed work on top of their master branch, rather than merging it in, to keep a mostly linear history. -When you have work in a topic branch and have determined that you want to integrate it, you move to that branch and run the rebase command to rebuild the changes on top of your current master (or `develop`, and so on) branch. +Other maintainers prefer to rebase or cherry-pick contributed work on top of their `master` branch, rather than merging it in, to keep a mostly linear history. +When you have work in a topic branch and have determined that you want to integrate it, you move to that branch and run the rebase command to rebuild the changes on top of your current `master` (or `develop`, and so on) branch. If that works well, you can fast-forward your `master` branch, and you'll end up with a linear project history. (((git commands, cherry-pick))) @@ -381,10 +381,10 @@ It takes the patch that was introduced in a commit and tries to reapply it on th This is useful if you have a number of commits on a topic branch and you want to integrate only one of them, or if you only have one commit on a topic branch and you'd prefer to cherry-pick it rather than run rebase. For example, suppose you have a project that looks like this: -.Example history before a cherry-pick. -image::images/rebasing-1.png[Example history before a cherry-pick.] +.Example history before a cherry-pick +image::images/rebasing-1.png[Example history before a cherry-pick] -If you want to pull commit `e43a6` into your master branch, you can run +If you want to pull commit `e43a6` into your `master` branch, you can run: [source,console] ---- @@ -397,17 +397,17 @@ Finished one cherry-pick. This pulls the same change introduced in `e43a6`, but you get a new commit SHA-1 value, because the date applied is different. Now your history looks like this: -.History after cherry-picking a commit on a topic branch. -image::images/rebasing-2.png[History after cherry-picking a commit on a topic branch.] +.History after cherry-picking a commit on a topic branch +image::images/rebasing-2.png[History after cherry-picking a commit on a topic branch] Now you can remove your topic branch and drop the commits you didn't want to pull in. ===== Rerere (((git commands, rerere)))(((rerere))) -If you're doing lots of merging and rebasing, or you're maintaining a long-lived topic branch, Git has a feature called ``rerere'' that can help. +If you're doing lots of merging and rebasing, or you're maintaining a long-lived topic branch, Git has a feature called "`rerere`" that can help. -Rerere stands for ``reuse recorded resolution'' -- it's a way of shortcutting manual conflict resolution. +Rerere stands for "`reuse recorded resolution`" -- it's a way of shortcutting manual conflict resolution. When rerere is enabled, Git will keep a set of pre- and post-images from successful merges, and if it notices that there's a conflict that looks exactly like one you've already fixed, it'll just use the fix from last time, without bothering you with it. This feature comes in two parts: a configuration setting and a command. @@ -517,7 +517,7 @@ $ ls *.tar.gz v1.6.2-rc1-20-g8c5b85c.tar.gz ---- -If someone opens that tarball, they get the latest snapshot of your project under a project directory. +If someone opens that tarball, they get the latest snapshot of your project under a `project` directory. You can also create a zip archive in much the same way, but by passing the `--format=zip` option to `git archive`: [source,console] @@ -533,7 +533,7 @@ You now have a nice tarball and a zip archive of your project release that you c (((git commands, shortlog))) It's time to email your mailing list of people who want to know what's happening in your project. A nice way of quickly getting a sort of changelog of what has been added to your project since your last release or email is to use the `git shortlog` command. -It summarizes all the commits in the range you give it; for example, the following gives you a summary of all the commits since your last release, if your last release was named v1.0.1: +It summarizes all the commits in the range you give it; for example, the following gives you a summary of all the commits since your last release, if your last release was named `v1.0.1`: [source,console] ---- @@ -553,4 +553,4 @@ Tom Preston-Werner (4): Regenerated gemspec for version 1.0.2 ---- -You get a clean summary of all the commits since v1.0.1, grouped by author, that you can email to your list. +You get a clean summary of all the commits since `v1.0.1`, grouped by author, that you can email to your list. diff --git a/book/06-github/callouts/1.pdf b/book/06-github/callouts/1.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/10.pdf b/book/06-github/callouts/10.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/2.pdf b/book/06-github/callouts/2.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/3.pdf b/book/06-github/callouts/3.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/4.pdf b/book/06-github/callouts/4.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/5.pdf b/book/06-github/callouts/5.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/6.pdf b/book/06-github/callouts/6.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/7.pdf b/book/06-github/callouts/7.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/8.pdf b/book/06-github/callouts/8.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/callouts/9.pdf b/book/06-github/callouts/9.pdf old mode 100755 new mode 100644 diff --git a/book/06-github/sections/1-setting-up-account.asc b/book/06-github/sections/1-setting-up-account.asc index 56fc5c84e..2ab023ec0 100644 --- a/book/06-github/sections/1-setting-up-account.asc +++ b/book/06-github/sections/1-setting-up-account.asc @@ -2,10 +2,10 @@ (((GitHub, user accounts))) The first thing you need to do is set up a free user account. -Simply visit https://github.com[], choose a user name that isn't already taken, provide an email address and a password, and click the big green ``Sign up for GitHub'' button. +Simply visit https://github.com[^], choose a user name that isn't already taken, provide an email address and a password, and click the big green "`Sign up for GitHub`" button. -.The GitHub sign-up form. -image::images/signup.png[The GitHub sign-up form.] +.The GitHub sign-up form +image::images/signup.png[The GitHub sign-up form] The next thing you'll see is the pricing page for upgraded plans, but it's safe to ignore this for now. GitHub will send you an email to verify the address you provided. @@ -13,8 +13,10 @@ Go ahead and do this; it's pretty important (as we'll see later). [NOTE] ==== -GitHub provides all of its functionality with free accounts, with the limitation that all of your projects are fully public (everyone has read access). -GitHub's paid plans also include the option of creating private projects, but we won't be covering those in this book. +GitHub provides almost all of its functionality with free accounts, except some advanced features. + +GitHub's paid plans include advanced tools and features as well as increased limits for free services, but we won't be covering those in this book. +To get more information about available plans and their comparison, visit https://github.com/pricing[^]. ==== Clicking the Octocat logo at the top-left of the screen will take you to your dashboard page. @@ -27,18 +29,18 @@ As of right now, you're fully able to connect with Git repositories using the `h However, to simply clone public projects, you don't even need to sign up - the account we just created comes into play when we fork projects and push to our forks a bit later. If you'd like to use SSH remotes, you'll need to configure a public key. -(If you don't already have one, see <>.) +If you don't already have one, see <>. Open up your account settings using the link at the top-right of the window: -.The ``Account settings'' link. -image::images/account-settings.png[The ``Account settings'' link.] +.The "`Account settings`" link +image::images/account-settings.png[The “Account settings” link] -Then select the ``SSH keys'' section along the left-hand side. +Then select the "`SSH keys`" section along the left-hand side. -.The ``SSH keys'' link. -image::images/ssh-keys.png[The ``SSH keys'' link.] +.The "`SSH keys`" link +image::images/ssh-keys.png[The “SSH keys” link] -From there, click the "`Add an SSH key`" button, give your key a name, paste the contents of your `~/.ssh/id_rsa.pub` (or whatever you named it) public-key file into the text area, and click ``Add key''. +From there, click the "`Add an SSH key`" button, give your key a name, paste the contents of your `~/.ssh/id_rsa.pub` (or whatever you named it) public-key file into the text area, and click "`Add key`". [NOTE] ==== @@ -50,19 +52,19 @@ You can name each of your keys (e.g. "My Laptop" or "Work Account") so that if y ==== Your Avatar Next, if you wish, you can replace the avatar that is generated for you with an image of your choosing. -First go to the ``Profile'' tab (above the SSH Keys tab) and click ``Upload new picture''. +First go to the "`Profile`" tab (above the SSH Keys tab) and click "`Upload new picture`". -.The ``Profile'' link. -image::images/your-profile.png[The ``Profile'' link.] +.The "`Profile`" link +image::images/your-profile.png[The “Profile” link] We'll choose a copy of the Git logo that is on our hard drive and then we get a chance to crop it. -.Crop your avatar -image::images/avatar-crop.png[Crop your uploaded avatar.] +.Crop your uploaded avatar +image::images/avatar-crop.png[Crop your uploaded avatar] Now anywhere you interact on the site, people will see your avatar next to your username. -If you happen to have uploaded an avatar to the popular Gravatar service (often used for Wordpress accounts), that avatar will be used by default and you don't need to do this step. +If you happen to have uploaded an avatar to the popular Gravatar service (often used for WordPress accounts), that avatar will be used by default and you don't need to do this step. ==== Your Email Addresses @@ -70,8 +72,8 @@ The way that GitHub maps your Git commits to your user is by email address. If you use multiple email addresses in your commits and you want GitHub to link them up properly, you need to add all the email addresses you have used to the Emails section of the admin section. [[_add_email_addresses]] -.Add email addresses -image::images/email-settings.png[Add all your email addresses.] +.Add all your email addresses +image::images/email-settings.png[Add all your email addresses] In <<_add_email_addresses>> we can see some of the different states that are possible. The top address is verified and set as the primary address, meaning that is where you'll get any notifications and receipts. @@ -81,7 +83,7 @@ If GitHub sees any of these in commit messages in any repository on the site, it ==== Two Factor Authentication -Finally, for extra security, you should definitely set up Two-factor Authentication or ``2FA''. +Finally, for extra security, you should definitely set up Two-factor Authentication or "`2FA`". Two-factor Authentication is an authentication mechanism that is becoming more and more popular recently to mitigate the risk of your account being compromised if your password is stolen somehow. Turning it on will make GitHub ask you for two different methods of authentication, so that if one of them is compromised, an attacker will not be able to access your account. @@ -90,6 +92,6 @@ You can find the Two-factor Authentication setup under the Security tab of your .2FA in the Security Tab image::images/2fa-1.png[2FA in the Security Tab] -If you click on the ``Set up two-factor authentication'' button, it will take you to a configuration page where you can choose to use a phone app to generate your secondary code (a ``time based one-time password''), or you can have GitHub send you a code via SMS each time you need to log in. +If you click on the "`Set up two-factor authentication`" button, it will take you to a configuration page where you can choose to use a phone app to generate your secondary code (a "`time based one-time password`"), or you can have GitHub send you a code via SMS each time you need to log in. After you choose which method you prefer and follow the instructions for setting up 2FA, your account will then be a little more secure and you will have to provide a code in addition to your password whenever you log into GitHub. diff --git a/book/06-github/sections/2-contributing.asc b/book/06-github/sections/2-contributing.asc index f280ee6f6..1dffbd9a5 100644 --- a/book/06-github/sections/2-contributing.asc +++ b/book/06-github/sections/2-contributing.asc @@ -5,27 +5,26 @@ Now that our account is set up, let's walk through some details that could be us ==== Forking Projects (((forking))) -If you want to contribute to an existing project to which you don't have push access, you can ``fork'' the project. -When you ``fork'' a project, GitHub will make a copy of the project that is entirely yours; it lives in your namespace, and you can push to it. +If you want to contribute to an existing project to which you don't have push access, you can "`fork`" the project. +When you "`fork`" a project, GitHub will make a copy of the project that is entirely yours; it lives in your namespace, and you can push to it. [NOTE] ==== -Historically, the term ``fork'' has been somewhat negative in context, meaning that someone took an open source project in a different direction, sometimes creating a competing project and splitting the contributors. -In GitHub, a ``fork'' is simply the same project in your own namespace, allowing you to make changes to a project publicly as a way to contribute in a more open manner. +Historically, the term "`fork`" has been somewhat negative in context, meaning that someone took an open source project in a different direction, sometimes creating a competing project and splitting the contributors. +In GitHub, a "`fork`" is simply the same project in your own namespace, allowing you to make changes to a project publicly as a way to contribute in a more open manner. ==== This way, projects don't have to worry about adding users as collaborators to give them push access. People can fork a project, push to it, and contribute their changes back to the original repository by creating what's called a Pull Request, which we'll cover next. This opens up a discussion thread with code review, and the owner and the contributor can then communicate about the change until the owner is happy with it, at which point the owner can merge it in. -To fork a project, visit the project page and click the ``Fork'' button at the top-right of the page. +To fork a project, visit the project page and click the "`Fork`" button at the top-right of the page. -.The ``Fork'' button. -image::images/forkbutton.png[The ``Fork'' button.] +.The "`Fork`" button +image::images/forkbutton.png[The “Fork” button] After a few seconds, you'll be taken to your new project page, with your own writeable copy of the code. - [[ch06-github_flow]] ==== The GitHub Flow @@ -36,32 +35,39 @@ It is centered on the <> workflow covered in < Here's how it generally works: -1. Fork the project +1. Fork the project. 2. Create a topic branch from `master`. 3. Make some commits to improve the project. 4. Push this branch to your GitHub project. 5. Open a Pull Request on GitHub. 6. Discuss, and optionally continue committing. 7. The project owner merges or closes the Pull Request. -8. Sync the updated master back to your fork. +8. Sync the updated `master` back to your fork. This is basically the Integration Manager workflow covered in <>, but instead of using email to communicate and review changes, teams use GitHub's web based tools. Let's walk through an example of proposing a change to an open source project hosted on GitHub using this flow. +[TIP] +==== +You can use the official *GitHub CLI* tool instead of the GitHub web interface for most things. +The tool can be used on Windows, macOS, and Linux systems. +Go to the https://cli.github.com/[GitHub CLI homepage^] for installation instructions and the manual. +==== + ===== Creating a Pull Request -Tony is looking for code to run on his Arduino programmable microcontroller and has found a great program file on GitHub at https://github.com/schacon/blink[]. +Tony is looking for code to run on his Arduino programmable microcontroller and has found a great program file on GitHub at https://github.com/schacon/blink[^]. -.The project we want to contribute to. -image::images/blink-01-start.png[The project we want to contribute to.] +.The project we want to contribute to +image::images/blink-01-start.png[The project we want to contribute to] The only problem is that the blinking rate is too fast. We think it's much nicer to wait 3 seconds instead of 1 in between each state change. So let's improve the program and submit it back to the project as a proposed change. First, we click the 'Fork' button as mentioned earlier to get our own copy of the project. -Our user name here is ``tonychacon'' so our copy of this project is at `https://github.com/tonychacon/blink` and that's where we can edit it. +Our user name here is "`tonychacon`" so our copy of this project is at `https://github.com/tonychacon/blink` and that's where we can edit it. We will clone it locally, create a topic branch, make the code change and finally push that change back up to GitHub. [source,console] @@ -91,8 +97,8 @@ void loop() { [-delay(1000);-]{+delay(3000);+} // wait for a second } -$ git commit -a -m 'three seconds is better' <5> -[slow-blink 5ca509d] three seconds is better +$ git commit -a -m 'Change delay to 3 seconds' <5> +[slow-blink 5ca509d] Change delay to 3 seconds 1 file changed, 2 insertions(+), 2 deletions(-) $ git push origin slow-blink <6> @@ -107,16 +113,16 @@ To https://github.com/tonychacon/blink * [new branch] slow-blink -> slow-blink ---- -<1> Clone our fork of the project locally -<2> Create a descriptive topic branch -<3> Make our change to the code -<4> Check that the change is good -<5> Commit our change to the topic branch -<6> Push our new topic branch back up to our GitHub fork +<1> Clone our fork of the project locally. +<2> Create a descriptive topic branch. +<3> Make our change to the code. +<4> Check that the change is good. +<5> Commit our change to the topic branch. +<6> Push our new topic branch back up to our GitHub fork. Now if we go back to our fork on GitHub, we can see that GitHub noticed that we pushed a new topic branch up and presents us with a big green button to check out our changes and open a Pull Request to the original project. -You can alternatively go to the ``Branches'' page at `https://github.com///branches` to locate your branch and open a new Pull Request from there. +You can alternatively go to the "`Branches`" page at `\https://github.com///branches` to locate your branch and open a new Pull Request from there. .Pull Request button image::images/blink-02-pr.png[Pull Request button] @@ -125,10 +131,10 @@ image::images/blink-02-pr.png[Pull Request button] If we click that green button, we'll see a screen that asks us to give our Pull Request a title and description. It is almost always worthwhile to put some effort into this, since a good description helps the owner of the original project determine what you were trying to do, whether your proposed changes are correct, and whether accepting the changes would improve the original project. -We also see a list of the commits in our topic branch that are ``ahead'' of the `master` branch (in this case, just the one) and a unified diff of all the changes that will be made should this branch get merged by the project owner. +We also see a list of the commits in our topic branch that are "`ahead`" of the `master` branch (in this case, just the one) and a unified diff of all the changes that will be made should this branch get merged by the project owner. .Pull Request creation page -image::images/blink-03-pull-request-open.png[Pull Request creation] +image::images/blink-03-pull-request-open.png[Pull Request creation page] When you hit the 'Create pull request' button on this screen, the owner of the project you forked will get a notification that someone is suggesting a change and will link to a page that has all of this information on it. @@ -147,14 +153,14 @@ Where this conversation may take place over email in the workflows presented in The project owner can review the unified diff and leave a comment by clicking on any of the lines. .Comment on a specific line of code in a Pull Request -image::images/blink-04-pr-comment.png[PR line comment] +image::images/blink-04-pr-comment.png[Comment on a specific line of code in a Pull Request] Once the maintainer makes this comment, the person who opened the Pull Request (and indeed, anyone else watching the repository) will get a notification. We'll go over customizing this later, but if he had email notifications turned on, Tony would get an email like this: [[_email_notification]] .Comments sent as email notifications -image::images/blink-04-email.png[Email notification] +image::images/blink-04-email.png[Comments sent as email notifications] Anyone can also leave general comments on the Pull Request. In <<_pr_discussion>> we can see an example of the project owner both commenting on a line of code and then leaving a general comment in the discussion section. @@ -162,7 +168,7 @@ You can see that the code comments are brought into the conversation as well. [[_pr_discussion]] .Pull Request discussion page -image::images/blink-05-general-comment.png[PR discussion page] +image::images/blink-05-general-comment.png[Pull Request discussion page] Now the contributor can see what they need to do in order to get their change accepted. Luckily this is very straightforward. @@ -173,15 +179,15 @@ Adding commits to an existing Pull Request doesn't trigger a notification, so on [[_pr_final]] .Pull Request final -image::images/blink-06-final.png[PR final] +image::images/blink-06-final.png[Pull Request final] -An interesting thing to notice is that if you click on the ``Files Changed'' tab on this Pull Request, you'll get the ``unified'' diff -- that is, the total aggregate difference that would be introduced to your main branch if this topic branch was merged in. +An interesting thing to notice is that if you click on the "`Files Changed`" tab on this Pull Request, you'll get the "`unified`" diff -- that is, the total aggregate difference that would be introduced to your main branch if this topic branch was merged in. In `git diff` terms, it basically automatically shows you `git diff master...` for the branch this Pull Request is based on. See <> for more about this type of diff. The other thing you'll notice is that GitHub checks to see if the Pull Request merges cleanly and provides a button to do the merge for you on the server. This button only shows up if you have write access to the repository and a trivial merge is possible. -If you click it GitHub will perform a ``non-fast-forward'' merge, meaning that even if the merge *could* be a fast-forward, it will still create a merge commit. +If you click it GitHub will perform a "`non-fast-forward`" merge, meaning that even if the merge *could* be a fast-forward, it will still create a merge commit. If you would prefer, you can simply pull the branch down and merge it locally. If you merge this branch into the `master` branch and push it to GitHub, the Pull Request will automatically be closed. @@ -213,7 +219,7 @@ When code is proposed with a Pull Request and the maintainers or community sugge For instance, if you go back and look again at <<_pr_final>>, you'll notice that the contributor did not rebase his commit and send another Pull Request. Instead they added new commits and pushed them to the existing branch. This way if you go back and look at this Pull Request in the future, you can easily find all of the context of why decisions were made. -Pushing the ``Merge'' button on the site purposefully creates a merge commit that references the Pull Request so that it's easy to go back and research the original conversation if necessary. +Pushing the "`Merge`" button on the site purposefully creates a merge commit that references the Pull Request so that it's easy to go back and research the original conversation if necessary. ===== Keeping up with Upstream @@ -222,7 +228,7 @@ GitHub will test this for you and let you know at the bottom of every Pull Reque [[_pr_fail]] .Pull Request does not merge cleanly -image::images/pr-01-fail.png[PR merge failure] +image::images/pr-01-fail.png[Pull Request does not merge cleanly] If you see something like <<_pr_fail>>, you'll want to fix your branch so that it turns green and the maintainer doesn't have to do extra work. @@ -234,7 +240,7 @@ What matters is the history and the final merge, so rebasing isn't getting you m If you want to merge in the target branch to make your Pull Request mergeable, you would add the original repository as a new remote, fetch from it, merge the main branch of that repository into your topic branch, fix any issues and finally push it back up to the same branch you opened the Pull Request on. -For example, let's say that in the ``tonychacon'' example we were using before, the original author made a change that would create a conflict in the Pull Request. +For example, let's say that in the "`tonychacon`" example we were using before, the original author made a change that would create a conflict in the Pull Request. Let's go through those steps. [source,console] @@ -270,17 +276,17 @@ To https://github.com/tonychacon/blink ef4725c..3c8d735 slower-blink -> slow-blink ---- -<1> Add the original repository as a remote named ``upstream'' -<2> Fetch the newest work from that remote -<3> Merge the main branch of that repository into your topic branch -<4> Fix the conflict that occurred -<5> Push back up to the same topic branch +<1> Add the original repository as a remote named `upstream`. +<2> Fetch the newest work from that remote. +<3> Merge the main branch of that repository into your topic branch. +<4> Fix the conflict that occurred. +<5> Push back up to the same topic branch. Once you do that, the Pull Request will be automatically updated and re-checked to see if it merges cleanly. [[_pr_merge_fix]] .Pull Request now merges cleanly -image::images/pr-02-merge-fix.png[PR fixed] +image::images/pr-02-merge-fix.png[Pull Request now merges cleanly] One of the great things about Git is that you can do that continuously. If you have a very long-running project, you can easily merge from the target branch over and over again and only have to deal with conflicts that have arisen since the last time that you merged, making the process very manageable. @@ -291,13 +297,13 @@ Instead, push the rebased branch to a new branch on GitHub and open a brand new ===== References -Your next question may be ``How do I reference the old Pull Request?''. +Your next question may be "`How do I reference the old Pull Request?`". It turns out there are many, many ways to reference other things almost anywhere you can write in GitHub. Let's start with how to cross-reference another Pull Request or an Issue. All Pull Requests and Issues are assigned numbers and they are unique within the project. -For example, you can't have Pull Request #3 _and_ Issue #3. -If you want to reference any Pull Request or Issue from any other one, you can simply put `#` in any comment or description. +For example, you can't have Pull Request +#3+ _and_ Issue +#3+. +If you want to reference any Pull Request or Issue from any other one, you can simply put `+#+` in any comment or description. You can also be more specific if the Issue or Pull request lives somewhere else; write `username#` if you're referring to an Issue or Pull Request in a fork of the repository you're in, or `username/repo#` to reference something in another repository. Let's look at an example. @@ -306,14 +312,14 @@ We also want to reference an issue in the fork of the repository and an issue in We can fill out the description just like <<_pr_references>>. [[_pr_references]] -.Cross references in a Pull Request. -image::images/mentions-01-syntax.png[PR references] +.Cross references in a Pull Request +image::images/mentions-01-syntax.png[Cross references in a Pull Request] When we submit this pull request, we'll see all of that rendered like <<_pr_references_render>>. [[_pr_references_render]] -.Cross references rendered in a Pull Request. -image::images/mentions-02-render.png[PR references rendered] +.Cross references rendered in a Pull Request +image::images/mentions-02-render.png[Cross references rendered in a Pull Request] Notice that the full GitHub URL we put in there was shortened to just the information needed. @@ -322,8 +328,8 @@ This means that anyone who visits this Pull Request and sees that it is closed c The link will look something like <<_pr_closed>>. [[_pr_closed]] -.Link back to the new Pull Request in the closed Pull Request timeline. -image::images/mentions-03-closed.png[PR closed] +.Link back to the new Pull Request in the closed Pull Request timeline +image::images/mentions-03-closed.png[Link back to the new Pull Request in the closed Pull Request timeline] In addition to issue numbers, you can also reference a specific commit by SHA-1. You have to specify a full 40 character SHA-1, but if GitHub sees that in a comment, it will link directly to the commit. @@ -332,14 +338,14 @@ Again, you can reference commits in forks or other repositories in the same way ==== GitHub Flavored Markdown Linking to other Issues is just the beginning of interesting things you can do with almost any text box on GitHub. -In Issue and Pull Request descriptions, comments, code comments and more, you can use what is called ``GitHub Flavored Markdown''. +In Issue and Pull Request descriptions, comments, code comments and more, you can use what is called "`GitHub Flavored Markdown`". Markdown is like writing in plain text but which is rendered richly. See <<_example_markdown>> for an example of how comments or text can be written and then rendered using Markdown. [[_example_markdown]] -.An example of GitHub Flavored Markdown as written and as rendered. -image::images/markdown-01-example.png[Example Markdown] +.An example of GitHub Flavored Markdown as written and as rendered +image::images/markdown-01-example.png[An example of GitHub Flavored Markdown as written and as rendered] The GitHub flavor of Markdown adds more things you can do beyond the basic Markdown syntax. These can all be really useful when creating useful Pull Request or Issue comments or descriptions. @@ -359,11 +365,11 @@ You can create a task list like this: - [ ] Document the code ---- -If we include this in the description of our Pull Request or Issue, we'll see it rendered like <<_eg_task_lists>> +If we include this in the description of our Pull Request or Issue, we'll see it rendered like <<_eg_task_lists>>. [[_eg_task_lists]] -.Task lists rendered in a Markdown comment. -image::images/markdown-02-tasks.png[Example Task List] +.Task lists rendered in a Markdown comment +image::images/markdown-02-tasks.png[Task lists rendered in a Markdown comment] This is often used in Pull Requests to indicate what all you would like to get done on the branch before the Pull Request will be ready to merge. The really cool part is that you can simply click the checkboxes to update the comment -- you don't have to edit the Markdown directly to check tasks off. @@ -374,8 +380,8 @@ This helps people break down Pull Requests into subtasks and helps other people You can see an example of this in <<_task_list_progress>>. [[_task_list_progress]] -.Task list summary in the Pull Request list. -image::images/markdown-03-task-summary.png[Example Task List] +.Task list summary in the Pull Request list +image::images/markdown-03-task-summary.png[Task list summary in the Pull Request list] These are incredibly useful when you open a Pull Request early and use it to track your progress through the implementation of the feature. @@ -385,7 +391,7 @@ You can also add code snippets to comments. This is especially useful if you want to present something that you _could_ try to do before actually implementing it as a commit on your branch. This is also often used to add example code of what is not working or what this Pull Request could implement. -To add a snippet of code you have to ``fence'' it in backticks. +To add a snippet of code you have to "`fence`" it in backticks. [source,text] ---- @@ -401,8 +407,8 @@ If you add a language name like we did there with 'java', GitHub will also try t In the case of the above example, it would end up rendering like <<_md_code>>. [[_md_code]] -.Rendered fenced code example. -image::images/markdown-04-fenced-code.png[Rendered fenced code] +.Rendered fenced code example +image::images/markdown-04-fenced-code.png[Rendered fenced code example] ===== Quoting @@ -423,8 +429,8 @@ How big are these slings and in particular, these arrows? Once rendered, the comment will look like <<_md_quote>>. [[_md_quote]] -.Rendered quoting example. -image::images/markdown-05-quote.png[Rendered quoting] +.Rendered quoting example +image::images/markdown-05-quote.png[Rendered quoting example] ===== Emoji @@ -434,8 +440,8 @@ There is even an emoji helper in GitHub. If you are typing a comment and you start with a `:` character, an autocompleter will help you find what you're looking for. [[_md_emoji_auto]] -.Emoji autocompleter in action. -image::images/markdown-06-emoji-complete.png[Emoji autocompleter] +.Emoji autocompleter in action +image::images/markdown-06-emoji-complete.png[Emoji autocompleter in action] Emojis take the form of `::` anywhere in the comment. For instance, you could write something like this: @@ -454,18 +460,17 @@ I :eyes: that :bug: and I :cold_sweat:. When rendered, it would look something like <<_md_emoji>>. [[_md_emoji]] -.Heavy emoji commenting. -image::images/markdown-07-emoji.png[Emoji] - -Note that this is incredibly useful, but it does add an element of fun and emotion to a medium that is otherwise hard to convey emotion in. +.Heavy emoji commenting +image::images/markdown-07-emoji.png[Heavy emoji commenting] +Not that this is incredibly useful, but it does add an element of fun and emotion to a medium that is otherwise hard to convey emotion in. [NOTE] ==== There are actually quite a number of web services that make use of emoji characters these days. A great cheat sheet to reference to find emoji that expresses what you want to say can be found at: -https://www.webfx.com/tools/emoji-cheat-sheet/ +https://www.webfx.com/tools/emoji-cheat-sheet/[^] ==== ===== Images @@ -474,10 +479,10 @@ This isn't technically GitHub Flavored Markdown, but it is incredibly useful. In addition to adding Markdown image links to comments, which can be difficult to find and embed URLs for, GitHub allows you to drag and drop images into text areas to embed them. [[_md_drag]] -.Drag and drop images to upload them and auto-embed them. -image::images/markdown-08-drag-drop.png[Drag and drop images] +.Drag and drop images to upload them and auto-embed them +image::images/markdown-08-drag-drop.png[Drag and drop images to upload them and auto-embed them] -If you look at <<_md_drag>>, you can see a small ``Parsed as Markdown'' hint above the text area. +If you look at <<_md_drag>>, you can see a small "`Parsed as Markdown`" hint above the text area. Clicking on that will give you a full cheat sheet of everything you can do with Markdown on GitHub. [[_fetch_and_push_on_different_repositories]] @@ -514,14 +519,16 @@ You can automate this work with a bit of configuration: [source,console] ---- $ git remote add progit https://github.com/progit/progit2.git <1> -$ git branch --set-upstream-to=progit/master master <2> -$ git config --local remote.pushDefault origin <3> +$ git fetch progit <2> +$ git branch --set-upstream-to=progit/master master <3> +$ git config --local remote.pushDefault origin <4> ---- <1> Add the source repository and give it a name. Here, I have chosen to call it `progit`. -<2> Set your `master` branch to fetch from the `progit` remote. -<3> Define the default push repository to `origin`. +<2> Get a reference on progit's branches, in particular `master`. +<3> Set your `master` branch to fetch from the `progit` remote. +<4> Define the default push repository to `origin`. Once this is done, the workflow becomes much simpler: diff --git a/book/06-github/sections/3-maintaining.asc b/book/06-github/sections/3-maintaining.asc index f174e15e9..2505e86a6 100644 --- a/book/06-github/sections/3-maintaining.asc +++ b/book/06-github/sections/3-maintaining.asc @@ -6,28 +6,28 @@ Now that we're comfortable contributing to a project, let's look at the other si ==== Creating a New Repository Let's create a new repository to share our project code with. -Start by clicking the ``New repository'' button on the right-hand side of the dashboard, or from the `+` button in the top toolbar next to your username as seen in <<_new_repo_dropdown>>. +Start by clicking the "`New repository`" button on the right-hand side of the dashboard, or from the `+` button in the top toolbar next to your username as seen in <<_new_repo_dropdown>>. -.The ``Your repositories'' area. -image::images/newrepo.png[The ``Your repositories'' area.] +.The "`Your repositories`" area +image::images/newrepo.png[The “Your repositories” area] [[_new_repo_dropdown]] -.The ``New repository'' dropdown. -image::images/new-repo.png[The ``new repository'' dropdown.] +.The "`New repository`" dropdown +image::images/new-repo.png[The “New repository” dropdown] -This takes you to the ``new repository'' form: +This takes you to the "`new repository`" form: -.The ``new repository'' form. -image::images/newrepoform.png[The ``new repository'' form.] +.The "`new repository`" form +image::images/newrepoform.png[The “new repository” form] All you really have to do here is provide a project name; the rest of the fields are completely optional. -For now, just click the ``Create Repository'' button, and boom – you have a new repository on GitHub, named `/`. +For now, just click the "`Create Repository`" button, and boom -- you have a new repository on GitHub, named `/`. Since you have no code there yet, GitHub will show you instructions for how to create a brand-new Git repository, or connect an existing Git project. We won't belabor this here; if you need a refresher, check out <>. Now that your project is hosted on GitHub, you can give the URL to anyone you want to share your project with. -Every project on GitHub is accessible over HTTPS as `https://github.com//`, and over SSH as `git@github.com:/`. +Every project on GitHub is accessible over HTTPS as `\https://github.com//`, and over SSH as `\git@github.com:/`. Git can fetch from and push to both of these URLs, but they are access-controlled based on the credentials of the user connecting to them. [NOTE] @@ -39,22 +39,22 @@ The HTTPS one is also exactly the same URL they would paste into a browser to vi ==== Adding Collaborators -If you're working with other people who you want to give commit access to, you need to add them as ``collaborators''. +If you're working with other people who you want to give commit access to, you need to add them as "`collaborators`". If Ben, Jeff, and Louise all sign up for accounts on GitHub, and you want to give them push access to your repository, you can add them to your project. -Doing so will give them ``push'' access, which means they have both read and write access to the project and Git repository. +Doing so will give them "`push`" access, which means they have both read and write access to the project and Git repository. -Click the ``Settings'' link at the bottom of the right-hand sidebar. +Click the "`Settings`" link at the bottom of the right-hand sidebar. -.The repository settings link. -image::images/reposettingslink.png[The repository settings link.] +.The repository settings link +image::images/reposettingslink.png[The repository settings link] -Then select ``Collaborators'' from the menu on the left-hand side. -Then, just type a username into the box, and click ``Add collaborator.'' +Then select "`Collaborators`" from the menu on the left-hand side. +Then, just type a username into the box, and click "`Add collaborator.`" You can repeat this as many times as you like to grant access to everyone you like. -If you need to revoke access, just click the ``X'' on the right-hand side of their row. +If you need to revoke access, just click the "`X`" on the right-hand side of their row. -.Repository collaborators. -image::images/collaborators.png[The repository collaborators box.] +.The repository collaborators box +image::images/collaborators.png[The repository collaborators box] ==== Managing Pull Requests @@ -63,7 +63,7 @@ Now that you have a project with some code in it and maybe even a few collaborat Pull Requests can either come from a branch in a fork of your repository or they can come from another branch in the same repository. The only difference is that the ones in a fork are often from people where you can't push to their branch and they can't push to yours, whereas with internal Pull Requests generally both parties can access the branch. -For these examples, let's assume you are ``tonychacon'' and you've created a new Arduino code project named ``fade''. +For these examples, let's assume you are "`tonychacon`" and you've created a new Arduino code project named "`fade`". [[_email_notifications]] ===== Email Notifications @@ -72,8 +72,8 @@ Someone comes along and makes a change to your code and sends you a Pull Request You should get an email notifying you about the new Pull Request and it should look something like <<_email_pr>>. [[_email_pr]] -.Email notification of a new Pull Request. -image::images/maint-01-email.png[Pull Request email notification] +.Email notification of a new Pull Request +image::images/maint-01-email.png[Email notification of a new Pull Request] There are a few things to notice about this email. It will give you a small diffstat -- a list of files that have changed in the Pull Request and by how much. @@ -100,19 +100,19 @@ You can comment on specific lines of code, comment on whole commits or comment o Every time someone else comments on the Pull Request you will continue to get email notifications so you know there is activity happening. They will each have a link to the Pull Request where the activity is happening and you can also directly respond to the email to comment on the Pull Request thread. -.Responses to emails are included in the thread. -image::images/maint-03-email-resp.png[Email response] +.Responses to emails are included in the thread +image::images/maint-03-email-resp.png[Responses to emails are included in the thread] Once the code is in a place you like and want to merge it in, you can either pull the code down and merge it locally, either with the `git pull ` syntax we saw earlier, or by adding the fork as a remote and fetching and merging. -If the merge is trivial, you can also just hit the ``Merge'' button on the GitHub site. -This will do a ``non-fast-forward'' merge, creating a merge commit even if a fast-forward merge was possible. +If the merge is trivial, you can also just hit the "`Merge`" button on the GitHub site. +This will do a "`non-fast-forward`" merge, creating a merge commit even if a fast-forward merge was possible. This means that no matter what, every time you hit the merge button, a merge commit is created. As you can see in <<_merge_button>>, GitHub gives you all of this information if you click the hint link. [[_merge_button]] -.Merge button and instructions for merging a Pull Request manually. -image::images/maint-02-merge.png[Merge button] +.Merge button and instructions for merging a Pull Request manually +image::images/maint-02-merge.png[Merge button and instructions for merging a Pull Request manually] If you decide you don't want to merge it, you can also just close the Pull Request and the person who opened it will be notified. @@ -125,10 +125,10 @@ This is a bit of an advanced trick and we'll go over the details of this a bit m GitHub actually advertises the Pull Request branches for a repository as sort of pseudo-branches on the server. By default you don't get them when you clone, but they are there in an obscured way and you can access them pretty easily. -To demonstrate this, we're going to use a low-level command (often referred to as a ``plumbing'' command, which we'll read about more in <>) called `ls-remote`. +To demonstrate this, we're going to use a low-level command (often referred to as a "`plumbing`" command, which we'll read about more in <>) called `ls-remote`. This command is generally not used in day-to-day Git operations but it's useful to show us what references are present on the server. -If we run this command against the ``blink'' repository we were using earlier, we will get a list of all the branches and tags and other references in the repository. +If we run this command against the "`blink`" repository we were using earlier, we will get a list of all the branches and tags and other references in the repository. [source,console] ---- @@ -161,7 +161,7 @@ From https://github.com/libgit2/libgit2 * branch refs/pull/958/head -> FETCH_HEAD ---- -This tells Git, ``Connect to the `origin` remote, and download the ref named `refs/pull/958/head`.'' +This tells Git, "`Connect to the `origin` remote, and download the ref named `refs/pull/958/head`.`" Git happily obeys, and downloads everything you need to construct that ref, and puts a pointer to the commit you want under `.git/FETCH_HEAD`. You can follow that up with `git merge FETCH_HEAD` into a branch you want to test it in, but that merge commit message looks a bit weird. Also, if you're reviewing a *lot* of pull requests, this gets tedious. @@ -177,7 +177,7 @@ It should look a bit like this: fetch = +refs/heads/*:refs/remotes/origin/* ---- -That line that begins with `fetch =` is a ``refspec.'' +That line that begins with `fetch =` is a "`refspec.`" It's a way of mapping names on the remote with names in your local `.git` directory. This particular one tells Git, "the things on the remote that are under `refs/heads` should go in my local repository under `refs/remotes/origin`." You can modify this section to add another refspec: @@ -190,7 +190,7 @@ You can modify this section to add another refspec: fetch = +refs/pull/*/head:refs/remotes/origin/pr/* ---- -That last line tells Git, ``All the refs that look like `refs/pull/123/head` should be stored locally like `refs/remotes/origin/pr/123`.'' +That last line tells Git, "`All the refs that look like `refs/pull/123/head` should be stored locally like `refs/remotes/origin/pr/123`.`" Now, if you save that file, and do a `git fetch`: [source,console] @@ -215,10 +215,9 @@ Switched to a new branch 'pr/2' ---- The eagle-eyed among you would note the `head` on the end of the remote portion of the refspec. -There's also a `refs/pull/#/merge` ref on the GitHub side, which represents the commit that would result if you push the ``merge'' button on the site. +There's also a `refs/pull/#/merge` ref on the GitHub side, which represents the commit that would result if you push the "`merge`" button on the site. This can allow you to test the merge before even hitting the button. - ===== Pull Requests on Pull Requests Not only can you open Pull Requests that target the main or `master` branch, you can actually open a Pull Request targeting any branch in the network. @@ -227,11 +226,11 @@ In fact, you can even target another Pull Request. If you see a Pull Request that is moving in the right direction and you have an idea for a change that depends on it or you're not sure is a good idea, or you just don't have push access to the target branch, you can open a Pull Request directly to it. When you go to open a Pull Request, there is a box at the top of the page that specifies which branch you're requesting to pull to and which you're requesting to pull from. -If you hit the ``Edit'' button at the right of that box you can change not only the branches but also which fork. +If you hit the "`Edit`" button at the right of that box you can change not only the branches but also which fork. [[_pr_targets]] -.Manually change the Pull Request target fork and branch. -image::images/maint-04-target.png[PR targets] +.Manually change the Pull Request target fork and branch +image::images/maint-04-target.png[Manually change the Pull Request target fork and branch] Here you can fairly easily specify to merge your new branch into another Pull Request or another fork of the project. @@ -241,8 +240,8 @@ GitHub also has a pretty nice notifications system built in that can come in han In any comment you can start typing a `@` character and it will begin to autocomplete with the names and usernames of people who are collaborators or contributors in the project. -.Start typing @ to mention someone. -image::images/maint-05-mentions.png[Mentions] +.Start typing @ to mention someone +image::images/maint-05-mentions.png[Start typing @ to mention someone] You can also mention a user who is not in that dropdown, but often the autocompleter can make it faster. @@ -250,22 +249,22 @@ Once you post a comment with a user mention, that user will be notified. This means that this can be a really effective way of pulling people into conversations rather than making them poll. Very often in Pull Requests on GitHub people will pull in other people on their teams or in their company to review an Issue or Pull Request. -If someone gets mentioned on a Pull Request or Issue, they will be ``subscribed'' to it and will continue getting notifications any time some activity occurs on it. +If someone gets mentioned on a Pull Request or Issue, they will be "`subscribed`" to it and will continue getting notifications any time some activity occurs on it. You will also be subscribed to something if you opened it, if you're watching the repository or if you comment on something. -If you no longer wish to receive notifications, there is an ``Unsubscribe'' button on the page you can click to stop receiving updates on it. +If you no longer wish to receive notifications, there is an "`Unsubscribe`" button on the page you can click to stop receiving updates on it. -.Unsubscribe from an Issue or Pull Request. -image::images/maint-06-unsubscribe.png[Unsubscribe] +.Unsubscribe from an Issue or Pull Request +image::images/maint-06-unsubscribe.png[Unsubscribe from an Issue or Pull Request] ===== The Notifications Page -When we mention ``notifications'' here with respect to GitHub, we mean a specific way that GitHub tries to get in touch with you when events happen and there are a few different ways you can configure them. -If you go to the ``Notification center'' tab from the settings page, you can see some of the options you have. +When we mention "`notifications`" here with respect to GitHub, we mean a specific way that GitHub tries to get in touch with you when events happen and there are a few different ways you can configure them. +If you go to the "`Notification center`" tab from the settings page, you can see some of the options you have. -.Notification center options. -image::images/maint-07-notifications.png[Notification center] +.Notification center options +image::images/maint-07-notifications.png[Notification center options] -The two choices are to get notifications over ``Email'' and over ``Web'' and you can choose either, neither or both for when you actively participate in things and for activity on repositories you are watching. +The two choices are to get notifications over "`Email`" and over "`Web`" and you can choose either, neither or both for when you actively participate in things and for activity on repositories you are watching. ====== Web Notifications @@ -273,7 +272,7 @@ Web notifications only exist on GitHub and you can only check them on GitHub. If you have this option selected in your preferences and a notification is triggered for you, you will see a small blue dot over your notifications icon at the top of your screen as seen in <<_not_center>>. [[_not_center]] -.Notification center. +.Notification center image::images/maint-08-notifications-page.png[Notification center] If you click on that, you will see a list of all the items you have been notified about, grouped by project. @@ -310,10 +309,10 @@ X-GitHub-Recipient-Address: tchacon@example.com There are a couple of interesting things here. If you want to highlight or re-route emails to this particular project or even Pull Request, the information in `Message-ID` gives you all the data in `///` format. -If this were an issue, for example, the `` field would have been ``issues'' rather than ``pull''. +If this was an issue, for example, the `` field would have been "`issues`" rather than "`pull`". -The `List-Post` and `List-Unsubscribe` fields mean that if you have a mail client that understands those, you can easily post to the list or ``Unsubscribe'' from the thread. -That would be essentially the same as clicking the ``mute'' button on the web version of the notification or ``Unsubscribe'' on the Issue or Pull Request page itself. +The `List-Post` and `List-Unsubscribe` fields mean that if you have a mail client that understands those, you can easily post to the list or "`Unsubscribe`" from the thread. +That would be essentially the same as clicking the "`mute`" button on the web version of the notification or "`Unsubscribe`" on the Issue or Pull Request page itself. It's also worth noting that if you have both email and web notifications enabled and you read the email version of the notification, the web version will be marked as read as well if you have images allowed in your mail client. @@ -325,7 +324,7 @@ There are a couple of special files that GitHub will notice if they are present The first is the `README` file, which can be of nearly any format that GitHub recognizes as prose. For example, it could be `README`, `README.md`, `README.asciidoc`, etc. -If GitHub sees a README file in your source, it will render it on the landing page of the project. +If GitHub sees a `README` file in your source, it will render it on the landing page of the project. Many teams use this file to hold all the relevant project information for someone who might be new to the repository or project. This generally includes things like: @@ -344,8 +343,8 @@ The other special file that GitHub recognizes is the `CONTRIBUTING` file. If you have a file named `CONTRIBUTING` with any file extension, GitHub will show <<_contrib_file>> when anyone starts opening a Pull Request. [[_contrib_file]] -.Opening a Pull Request when a CONTRIBUTING file exists. -image::images/maint-09-contrib.png[Contributing notice] +.Opening a Pull Request when a CONTRIBUTING file exists +image::images/maint-09-contrib.png[Opening a Pull Request when a CONTRIBUTING file exists] The idea here is that you can specify specific things you want or don't want in a Pull Request sent to your project. This way people may actually read the guidelines before opening the Pull Request. @@ -356,21 +355,21 @@ Generally there are not a lot of administrative things you can do with a single ===== Changing the Default Branch -If you are using a branch other than ``master'' as your default branch that you want people to open Pull Requests on or see by default, you can change that in your repository's settings page under the ``Options'' tab. +If you are using a branch other than "`master`" as your default branch that you want people to open Pull Requests on or see by default, you can change that in your repository's settings page under the "`Options`" tab. [[_default_branch]] -.Change the default branch for a project. -image::images/maint-10-default-branch.png[Default branch] +.Change the default branch for a project +image::images/maint-10-default-branch.png[Change the default branch for a project] Simply change the default branch in the dropdown and that will be the default for all major operations from then on, including which branch is checked out by default when someone clones the repository. ===== Transferring a Project -If you would like to transfer a project to another user or an organization in GitHub, there is a ``Transfer ownership'' option at the bottom of the same ``Options'' tab of your repository settings page that allows you to do this. +If you would like to transfer a project to another user or an organization in GitHub, there is a "`Transfer ownership`" option at the bottom of the same "`Options`" tab of your repository settings page that allows you to do this. [[_transfer_project]] -.Transfer a project to another GitHub user or Organization. -image::images/maint-11-transfer.png[Transfer] +.Transfer a project to another GitHub user or Organization +image::images/maint-11-transfer.png[Transfer a project to another GitHub user or Organization] This is helpful if you are abandoning a project and someone wants to take it over, or if your project is getting bigger and want to move it into an organization. diff --git a/book/06-github/sections/4-managing-organization.asc b/book/06-github/sections/4-managing-organization.asc index f3137e5dc..cdb2447ab 100644 --- a/book/06-github/sections/4-managing-organization.asc +++ b/book/06-github/sections/4-managing-organization.asc @@ -5,14 +5,14 @@ In addition to single-user accounts, GitHub has what are called Organizations. Like personal accounts, Organizational accounts have a namespace where all their projects exist, but many other things are different. These accounts represent a group of people with shared ownership of projects, and there are many tools to manage subgroups of those people. -Normally these accounts are used for Open Source groups (such as ``perl'' or ``rails'') or companies (such as ``google'' or ``twitter''). +Normally these accounts are used for Open Source groups (such as "`perl`" or "`rails`") or companies (such as "`google`" or "`twitter`"). ==== Organization Basics -An organization is pretty easy to create; just click on the ``+'' icon at the top-right of any GitHub page, and select ``New organization'' from the menu. +An organization is pretty easy to create; just click on the "`+`" icon at the top-right of any GitHub page, and select "`New organization`" from the menu. -.The ``New organization'' menu item. -image::images/neworg.png[The ``New organization'' menu item.] +.The "`New organization`" menu item +image::images/neworg.png[The “New organization” menu item] First you'll need to name your organization and provide an email address for a main point of contact for the group. Then you can invite other users to be co-owners of the account if you want to. @@ -22,7 +22,7 @@ Like personal accounts, organizations are free if everything you plan to store t As an owner in an organization, when you fork a repository, you'll have the choice of forking it to your organization's namespace. When you create new repositories you can create them either under your personal account or under any of the organizations that you are an owner in. -You also automatically ``watch'' any new repository created under these organizations. +You also automatically "`watch`" any new repository created under these organizations. Just like in <<_personal_avatar>>, you can upload an avatar for your organization to personalize it a bit. Also just like personal accounts, you have a landing page for the organization that lists all of your repositories and can be viewed by other people. @@ -40,17 +40,17 @@ Teams make this easy, without having to manage the collaborators for every indiv The Organization page shows you a simple dashboard of all the repositories, users and teams that are under this organization. [[_org_page]] -.The Organization page. -image::images/orgs-01-page.png[] +.The Organization page +image::images/orgs-01-page.png[The Organization page] To manage your Teams, you can click on the Teams sidebar on the right hand side of the page in <<_org_page>>. This will bring you to a page you can use to add members to the team, add repositories to the team or manage the settings and access control levels for the team. Each team can have read only, read/write or administrative access to the repositories. -You can change that level by clicking the ``Settings'' button in <<_team_page>>. +You can change that level by clicking the "`Settings`" button in <<_team_page>>. [[_team_page]] -.The Team page. -image::images/orgs-02-teams.png[] +.The Team page +image::images/orgs-02-teams.png[The Team page] When you invite someone to a team, they will get an email letting them know they've been invited. @@ -66,7 +66,7 @@ Organizations also give owners access to all the information about what went on You can go to the 'Audit Log' tab and see what events have happened at an organization level, who did them and where in the world they were done. [[_the_audit_log]] -.The Audit log. -image::images/orgs-03-audit.png[] +.The Audit log +image::images/orgs-03-audit.png[The Audit log] You can also filter down to specific types of events, specific places or specific people. diff --git a/book/06-github/sections/5-scripting.asc b/book/06-github/sections/5-scripting.asc index b85917d73..c755afa17 100644 --- a/book/06-github/sections/5-scripting.asc +++ b/book/06-github/sections/5-scripting.asc @@ -13,22 +13,22 @@ The Hooks and Services section of GitHub repository administration is the easies First we'll take a look at Services. Both the Hooks and Services integrations can be found in the Settings section of your repository, where we previously looked at adding Collaborators and changing the default branch of your project. -Under the ``Webhooks and Services'' tab you will see something like <<_services_hooks>>. +Under the "`Webhooks and Services`" tab you will see something like <<_services_hooks>>. [[_services_hooks]] -.Services and Hooks configuration section. -image::images/scripting-01-services.png[Services and hooks] +.Services and Hooks configuration section +image::images/scripting-01-services.png[Services and Hooks configuration section] There are dozens of services you can choose from, most of them integrations into other commercial and open source systems. Most of them are for Continuous Integration services, bug and issue trackers, chat room systems and documentation systems. We'll walk through setting up a very simple one, the Email hook. -If you choose ``email'' from the ``Add Service'' dropdown, you'll get a configuration screen like <<_service_config>>. +If you choose "`email`" from the "`Add Service`" dropdown, you'll get a configuration screen like <<_service_config>>. [[_service_config]] -.Email service configuration. -image::images/scripting-02-email-service.png[Email service] +.Email service configuration +image::images/scripting-02-email-service.png[Email service configuration] -In this case, if we hit the ``Add service'' button, the email address we specified will get an email every time someone pushes to the repository. +In this case, if we hit the "`Add service`" button, the email address we specified will get an email every time someone pushes to the repository. Services can listen for lots of different types of events, but most only listen for push events and then do something with that data. If there is a system you are using that you would like to integrate with GitHub, you should check here to see if there is an existing service integration available. @@ -42,15 +42,15 @@ You specify a URL and GitHub will post an HTTP payload to that URL on any event Generally the way this works is you can setup a small web service to listen for a GitHub hook payload and then do something with the data when it is received. -To enable a hook, you click the ``Add webhook'' button in <<_services_hooks>>. +To enable a hook, you click the "`Add webhook`" button in <<_services_hooks>>. This will bring you to a page that looks like <<_web_hook>>. [[_web_hook]] -.Web hook configuration. -image::images/scripting-03-webhook.png[Web hook] +.Web hook configuration +image::images/scripting-03-webhook.png[Web hook configuration] The configuration for a web hook is pretty simple. -In most cases you simply enter a URL and a secret key and hit ``Add webhook''. +In most cases you simply enter a URL and a secret key and hit "`Add webhook`". There are a few options for which events you want GitHub to send you a payload for -- the default is to only get a payload for the `push` event, when someone pushes new code to any branch of your repository. Let's see a small example of a web service you may set up to handle a web hook. @@ -102,12 +102,12 @@ For each hook you can dig down into when it was delivered, if it was successful This makes it incredibly easy to test and debug your hooks. [[_web_hook_debug]] -.Web hook debugging information. -image::images/scripting-04-webhook-debug.png[Webhook debug] +.Web hook debugging information +image::images/scripting-04-webhook-debug.png[Web hook debugging information] The other great feature of this is that you can redeliver any of the payloads to test your service easily. -For more information on how to write webhooks and all the different event types you can listen for, go to the GitHub Developer documentation at https://developer.github.com/webhooks/ +For more information on how to write webhooks and all the different event types you can listen for, go to the GitHub Developer documentation at https://docs.github.com/en/webhooks-and-events/webhooks/about-webhooks[^]. ==== The GitHub API @@ -123,7 +123,7 @@ In this section we'll learn how to authenticate and connect to the API, how to c The most basic thing you can do is a simple GET request on an endpoint that doesn't require authentication. This could be a user or read-only information on an open source project. -For example, if we want to know more about a user named ``schacon'', we can run something like this: +For example, if we want to know more about a user named "`schacon`", we can run something like this: [source,javascript] ---- @@ -165,18 +165,17 @@ hs_err_pid* } ---- - ==== Commenting on an Issue However, if you want to do an action on the website such as comment on an Issue or Pull Request or if you want to view or interact with private content, you'll need to authenticate. There are several ways to authenticate. You can use basic authentication with just your username and password, but generally it's a better idea to use a personal access token. -You can generate this from the ``Applications'' tab of your settings page. +You can generate this from the "`Applications`" tab of your settings page. [[_access_token]] -.Generate your access token from the ``Applications'' tab of your settings page. -image::images/scripting-05-access-token.png[Access Token] +.Generate your access token from the "`Applications`" tab of your settings page +image::images/scripting-05-access-token.png[Generate your access token from the “Applications” tab of your settings page] It will ask you which scopes you want for this token and a description. Make sure to use a good description so you feel comfortable removing the token when your script or application is no longer used. @@ -218,8 +217,8 @@ $ curl -H "Content-Type: application/json" \ Now if you go to that issue, you can see the comment that we just successfully posted as in <<_api_comment>>. [[_api_comment]] -.A comment posted from the GitHub API. -image::images/scripting-06-comment.png[API Comment] +.A comment posted from the GitHub API +image::images/scripting-06-comment.png[A comment posted from the GitHub API] You can use the API to do just about anything you can do on the website -- creating and setting milestones, assigning people to Issues and Pull Requests, creating and changing labels, accessing commit data, creating new commits and branches, opening, closing or merging Pull Requests, creating and editing teams, commenting on lines of code in a Pull Request, searching the site and on and on. @@ -279,16 +278,16 @@ end Hopefully this is fairly simple to follow. In this web hook handler we look through each commit that was just pushed, we look for the string 'Signed-off-by' in the commit message and finally we POST via HTTP to the `/repos///statuses/` API endpoint with the status. -In this case you can send a state ('success', 'failure', 'error'), a description of what happened, a target URL the user can go to for more information and a ``context'' in case there are multiple statuses for a single commit. -For example, a testing service may provide a status and a validation service like this may also provide a status -- the ``context'' field is how they're differentiated. +In this case you can send a state ('success', 'failure', 'error'), a description of what happened, a target URL the user can go to for more information and a "`context`" in case there are multiple statuses for a single commit. +For example, a testing service may provide a status and a validation service like this may also provide a status -- the "`context`" field is how they're differentiated. If someone opens a new Pull Request on GitHub and this hook is set up, you may see something like <<_commit_status>>. [[_commit_status]] -.Commit status via the API. -image::images/scripting-07-status.png[Commit status] +.Commit status via the API +image::images/scripting-07-status.png[Commit status via the API] -You can now see a little green check mark next to the commit that has a ``Signed-off-by'' string in the message and a red cross through the one where the author forgot to sign off. +You can now see a little green check mark next to the commit that has a "`Signed-off-by`" string in the message and a red cross through the one where the author forgot to sign off. You can also see that the Pull Request takes the status of the last commit on the branch and warns you if it is a failure. This is really useful if you're using this API for test results so you don't accidentally merge something where the last commit is failing tests. @@ -296,7 +295,7 @@ This is really useful if you're using this API for test results so you don't acc Though we've been doing nearly everything through `curl` and simple HTTP requests in these examples, several open-source libraries exist that make this API available in a more idiomatic way. At the time of this writing, the supported languages include Go, Objective-C, Ruby, and .NET. -Check out https://github.com/octokit[] for more information on these, as they handle much of the HTTP for you. +Check out https://github.com/octokit[^] for more information on these, as they handle much of the HTTP for you. Hopefully these tools can help you customize and modify GitHub to work better for your specific workflows. -For complete documentation on the entire API as well as guides for common tasks, check out https://developer.github.com[]. +For complete documentation on the entire API as well as guides for common tasks, check out https://docs.github.com/[^]. diff --git a/book/07-git-tools/callouts/1.pdf b/book/07-git-tools/callouts/1.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/10.pdf b/book/07-git-tools/callouts/10.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/2.pdf b/book/07-git-tools/callouts/2.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/3.pdf b/book/07-git-tools/callouts/3.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/4.pdf b/book/07-git-tools/callouts/4.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/5.pdf b/book/07-git-tools/callouts/5.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/6.pdf b/book/07-git-tools/callouts/6.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/7.pdf b/book/07-git-tools/callouts/7.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/8.pdf b/book/07-git-tools/callouts/8.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/callouts/9.pdf b/book/07-git-tools/callouts/9.pdf old mode 100755 new mode 100644 diff --git a/book/07-git-tools/git-credential-read-only b/book/07-git-tools/git-credential-read-only index b98833c4e..9e984dca9 100755 --- a/book/07-git-tools/git-credential-read-only +++ b/book/07-git-tools/git-credential-read-only @@ -11,7 +11,7 @@ OptionParser.new do |opts| end.parse! exit(0) unless ARGV[0].downcase == 'get' # <2> -exit(0) unless File.exists? path +exit(0) unless File.exist? path known = {} # <3> while line = STDIN.gets diff --git a/book/07-git-tools/sections/advanced-merging.asc b/book/07-git-tools/sections/advanced-merging.asc index d8b7e9d95..7ace27bcd 100644 --- a/book/07-git-tools/sections/advanced-merging.asc +++ b/book/07-git-tools/sections/advanced-merging.asc @@ -36,7 +36,7 @@ hello() ---- In our repository, we create a new branch named `whitespace` and proceed to change all the Unix line endings to DOS line endings, essentially changing every line of the file, but just with whitespace. -Then we change the line ``hello world'' to ``hello mundo''. +Then we change the line "`hello world`" to "`hello mundo`". [source,console] ---- @@ -45,8 +45,8 @@ Switched to a new branch 'whitespace' $ unix2dos hello.rb unix2dos: converting file hello.rb to DOS format ... -$ git commit -am 'converted hello.rb to DOS' -[whitespace 3270f76] converted hello.rb to DOS +$ git commit -am 'Convert hello.rb to DOS' +[whitespace 3270f76] Convert hello.rb to DOS 1 file changed, 7 insertions(+), 7 deletions(-) $ vim hello.rb @@ -65,8 +65,8 @@ index ac51efd..e85207e 100755 hello() -$ git commit -am 'hello mundo change' -[whitespace 6d338d2] hello mundo change +$ git commit -am 'Use Spanish instead of English' +[whitespace 6d338d2] Use Spanish instead of English 1 file changed, 1 insertion(+), 1 deletion(-) ---- @@ -91,8 +91,8 @@ index ac51efd..36c06c8 100755 puts 'hello world' end -$ git commit -am 'document the function' -[master bec6336] document the function +$ git commit -am 'Add comment documenting the function' +[master bec6336] Add comment documenting the function 1 file changed, 1 insertion(+) ---- @@ -164,12 +164,12 @@ What we really need to do is run the file we're trying to merge in through a `do So how would we do that? First, we get into the merge conflict state. -Then we want to get copies of my version of the file, their version (from the branch we're merging in) and the common version (from where both sides branched off). +Then we want to get copies of our version of the file, their version (from the branch we're merging in) and the common version (from where both sides branched off). Then we want to fix up either their side or our side and re-try the merge again for just this single file. Getting the three file versions is actually pretty easy. -Git stores all of these versions in the index under ``stages'' which each have numbers associated with them. -Stage 1 is the common ancestor, stage 2 is your version and stage 3 is from the `MERGE_HEAD`, the version you're merging in (``theirs''). +Git stores all of these versions in the index under "`stages`" which each have numbers associated with them. +Stage 1 is the common ancestor, stage 2 is your version and stage 3 is from the `MERGE_HEAD`, the version you're merging in ("`theirs`"). You can extract a copy of each of these versions of the conflicted file with the `git show` command and a special syntax. @@ -226,7 +226,7 @@ In the `ignore-space-change` merge, we actually ended up with a few lines with D If you want to get an idea before finalizing this commit about what was actually changed between one side or the other, you can ask `git diff` to compare what is in your working directory that you're about to commit as the result of the merge to any of these stages. Let's go through them all. -To compare your result to what you had in your branch before the merge, in other words, to see what the merge introduced, you can run `git diff --ours` +To compare your result to what you had in your branch before the merge, in other words, to see what the merge introduced, you can run `git diff --ours`: [source,console] ---- @@ -312,14 +312,14 @@ For this example, we have two longer lived branches that each have a few commits [source,console] ---- $ git log --graph --oneline --decorate --all -* f1270f7 (HEAD, master) update README -* 9af9d3b add a README -* 694971d update phrase to hola world -| * e3eb223 (mundo) add more tests -| * 7cff591 add testing script -| * c3ffff1 changed text to hello mundo +* f1270f7 (HEAD, master) Update README +* 9af9d3b Create README +* 694971d Update phrase to 'hola world' +| * e3eb223 (mundo) Add more tests +| * 7cff591 Create initial testing script +| * c3ffff1 Change text to 'hello mundo' |/ -* b7dcc89 initial hello world code +* b7dcc89 Initial hello world code ---- We now have three unique commits that live only on the `master` branch and three others that live on the `mundo` branch. @@ -362,7 +362,7 @@ This will re-checkout the file again and replace the merge conflict markers. This can be useful if you want to reset the markers and try to resolve them again. You can pass `--conflict` either `diff3` or `merge` (which is the default). -If you pass it `diff3`, Git will use a slightly different version of conflict markers, not only giving you the ``ours'' and ``theirs'' versions, but also the ``base'' version inline to give you more context. +If you pass it `diff3`, Git will use a slightly different version of conflict markers, not only giving you the "`ours`" and "`theirs`" versions, but also the "`base`" version inline to give you more context. [source,console] ---- @@ -397,7 +397,7 @@ $ git config --global merge.conflictstyle diff3 The `git checkout` command can also take `--ours` and `--theirs` options, which can be a really fast way of just choosing either one side or the other without merging things at all. -This can be particularly useful for conflicts of binary files where you can simply choose one side, or where you only want to merge certain files in from another branch - you can do the merge and then checkout certain files from one side or the other before committing. +This can be particularly useful for conflicts of binary files where you can simply choose one side, or where you only want to merge certain files in from another branch -- you can do the merge and then checkout certain files from one side or the other before committing. [[_merge_log]] ===== Merge Log @@ -406,17 +406,17 @@ Another useful tool when resolving merge conflicts is `git log`. This can help you get context on what may have contributed to the conflicts. Reviewing a little bit of history to remember why two lines of development were touching the same area of code can be really helpful sometimes. -To get a full list of all of the unique commits that were included in either branch involved in this merge, we can use the ``triple dot'' syntax that we learned in <>. +To get a full list of all of the unique commits that were included in either branch involved in this merge, we can use the "`triple dot`" syntax that we learned in <>. [source,console] ---- $ git log --oneline --left-right HEAD...MERGE_HEAD -< f1270f7 update README -< 9af9d3b add a README -< 694971d update phrase to hola world -> e3eb223 add more tests -> 7cff591 add testing script -> c3ffff1 changed text to hello mundo +< f1270f7 Update README +< 9af9d3b Create README +< 694971d Update phrase to 'hola world' +> e3eb223 Add more tests +> 7cff591 Create initial testing script +> c3ffff1 Change text to 'hello mundo' ---- That's a nice list of the six total commits involved, as well as which line of development each commit was on. @@ -427,8 +427,8 @@ If we add the `--merge` option to `git log`, it will only show the commits in ei [source,console] ---- $ git log --oneline --left-right --merge -< 694971d update phrase to hola world -> c3ffff1 changed text to hello mundo +< 694971d Update phrase to 'hola world' +> c3ffff1 Change text to 'hello mundo' ---- If you run that with the `-p` option instead, you get just the diffs to the file that ended up in conflict. @@ -462,8 +462,8 @@ index 0399cd5,59727f0..0000000 hello() ---- -The format is called ``Combined Diff'' and gives you two columns of data next to each line. -The first column shows you if that line is different (added or removed) between the ``ours'' branch and the file in your working directory and the second column does the same between the ``theirs'' branch and your working directory copy. +The format is called "`Combined Diff`" and gives you two columns of data next to each line. +The first column shows you if that line is different (added or removed) between the "`ours`" branch and the file in your working directory and the second column does the same between the "`theirs`" branch and your working directory copy. So in that example you can see that the `<<<<<<<` and `>>>>>>>` lines are in the working copy but were not in either side of the merge. This makes sense because the merge tool stuck them in there for our context, but we're expected to remove them. @@ -490,7 +490,7 @@ index 0399cd5,59727f0..0000000 hello() ---- -This shows us that ``hola world'' was in our side but not in the working copy, that ``hello mundo'' was in their side but not in the working copy and finally that ``hola mundo'' was not in either side but is now in the working copy. +This shows us that "`hola world`" was in our side but not in the working copy, that "`hello mundo`" was in their side but not in the working copy and finally that "`hola mundo`" was not in either side but is now in the working copy. This can be useful to review before committing the resolution. You can also get this from the `git log` for any merge to see how something was resolved after the fact. @@ -535,7 +535,7 @@ Merge commits are no different. Let's say you started work on a topic branch, accidentally merged it into `master`, and now your commit history looks like this: .Accidental merge commit -image::images/undomerge-start.png[Accidental merge commit.] +image::images/undomerge-start.png[Accidental merge commit] There are two ways to approach this problem, depending on what your desired outcome is. @@ -545,7 +545,7 @@ If the unwanted merge commit only exists on your local repository, the easiest a In most cases, if you follow the errant `git merge` with `git reset --hard HEAD~`, this will reset the branch pointers so they look like this: .History after `git reset --hard HEAD~` -image::images/undomerge-reset.png[History after `git reset --hard HEAD~`.] +image::images/undomerge-reset.png[History after `git reset --hard HEAD~`] We covered `reset` back in <>, so it shouldn't be too hard to figure out what's going on here. Here's a quick refresher: `reset --hard` usually goes through three steps: @@ -563,7 +563,7 @@ This approach also won't work if any other commits have been created since the m ===== Reverse the commit If moving the branch pointers around isn't going to work for you, Git gives you the option of making a new commit which undoes all the changes from an existing one. -Git calls this operation a ``revert'', and in this particular scenario, you'd invoke it like this: +Git calls this operation a "`revert`", and in this particular scenario, you'd invoke it like this: [source,console] ---- @@ -571,17 +571,17 @@ $ git revert -m 1 HEAD [master b1d8379] Revert "Merge branch 'topic'" ---- -The `-m 1` flag indicates which parent is the ``mainline'' and should be kept. +The `-m 1` flag indicates which parent is the "`mainline`" and should be kept. When you invoke a merge into `HEAD` (`git merge topic`), the new commit has two parents: the first one is `HEAD` (`C6`), and the second is the tip of the branch being merged in (`C4`). In this case, we want to undo all the changes introduced by merging in parent #2 (`C4`), while keeping all the content from parent #1 (`C6`). The history with the revert commit looks like this: .History after `git revert -m 1` -image::images/undomerge-revert.png[History after `git revert -m 1`.] +image::images/undomerge-revert.png[History after `git revert -m 1`] -The new commit `^M` has exactly the same contents as `C6`, so starting from here it's as if the merge never happened, except that the now-unmerged commits are still in `HEAD`'s history. -Git will get confused if you try to merge `topic` into `master` again: +The new commit `^M` has exactly the same contents as `C6`, so starting from here it's as if the merge never happened, except that the now-unmerged commits are still in ``HEAD```'s history. +Git will get confused if you try to merge ``topic`` into ``master`` again: [source,console] ---- @@ -593,7 +593,7 @@ There's nothing in `topic` that isn't already reachable from `master`. What's worse, if you add work to `topic` and merge again, Git will only bring in the changes _since_ the reverted merge: .History with a bad merge -image::images/undomerge-revert2.png[History with a bad merge.] +image::images/undomerge-revert2.png[History with a bad merge] The best way around this is to un-revert the original merge, since now you want to bring in the changes that were reverted out, *then* create a new merge commit: @@ -605,20 +605,20 @@ $ git merge topic ---- .History after re-merging a reverted merge -image::images/undomerge-revert3.png[History after re-merging a reverted merge.] +image::images/undomerge-revert3.png[History after re-merging a reverted merge] In this example, `M` and `^M` cancel out. `^^M` effectively merges in the changes from `C3` and `C4`, and `C8` merges in the changes from `C7`, so now `topic` is fully merged. ==== Other Types of Merges -So far we've covered the normal merge of two branches, normally handled with what is called the ``recursive'' strategy of merging. +So far we've covered the normal merge of two branches, normally handled with what is called the "`recursive`" strategy of merging. There are other ways to merge branches together however. Let's cover a few of them quickly. ===== Our or Theirs Preference -First of all, there is another useful thing we can do with the normal ``recursive'' mode of merging. +First of all, there is another useful thing we can do with the normal "`recursive`" mode of merging. We've already seen the `ignore-all-space` and `ignore-space-change` options which are passed with a `-X` but we can also tell Git to favor one side or the other when it sees a conflict. By default, when Git sees a conflict between two branches being merged, it will add merge conflict markers into your code and mark the file as conflicted and let you resolve it. @@ -628,7 +628,7 @@ If Git sees this, it will not add conflict markers. Any differences that are mergeable, it will merge. Any differences that conflict, it will simply choose the side you specify in whole, including binary files. -If we go back to the ``hello world'' example we were using before, we can see that merging in our branch causes conflicts. +If we go back to the "`hello world`" example we were using before, we can see that merging in our branch causes conflicts. [source,console] ---- @@ -652,13 +652,13 @@ Merge made by the 'recursive' strategy. create mode 100644 test.sh ---- -In that case, instead of getting conflict markers in the file with ``hello mundo'' on one side and ``hola world'' on the other, it will simply pick ``hola world''. +In that case, instead of getting conflict markers in the file with "`hello mundo`" on one side and "`hola world`" on the other, it will simply pick "`hola world`". However, all the other non-conflicting changes on that branch are merged successfully in. This option can also be passed to the `git merge-file` command we saw earlier by running something like `git merge-file --ours` for individual file merges. -If you want to do something like this but not have Git even try to merge changes from the other side in, there is a more draconian option, which is the ``ours'' merge _strategy_. -This is different from the ``ours'' recursive merge _option_. +If you want to do something like this but not have Git even try to merge changes from the other side in, there is a more draconian option, which is the "`ours`" merge _strategy_. +This is different from the "`ours`" recursive merge _option_. This will basically do a fake merge. It will record a new merge commit with both branches as parents, but it will not even look at the branch you're merging in. diff --git a/book/07-git-tools/sections/bundling.asc b/book/07-git-tools/sections/bundling.asc index 85dbf8235..79cb1b8a5 100644 --- a/book/07-git-tools/sections/bundling.asc +++ b/book/07-git-tools/sections/bundling.asc @@ -3,7 +3,7 @@ Though we've covered the common ways to transfer Git data over a network (HTTP, SSH, etc), there is actually one more way to do so that is not commonly used but can actually be quite useful. -Git is capable of ``bundling'' its data into a single file. +Git is capable of "`bundling`" its data into a single file. This can be useful in various scenarios. Maybe your network is down and you want to send changes to your co-workers. Perhaps you're working somewhere offsite and don't have access to the local network for security reasons. @@ -23,13 +23,13 @@ commit 9a466c572fe88b195efd356c3f2bbeccdb504102 Author: Scott Chacon Date: Wed Mar 10 07:34:10 2010 -0800 - second commit + Second commit commit b1ec3248f39900d2a406049d762aa68e9641be25 Author: Scott Chacon Date: Wed Mar 10 07:34:01 2010 -0800 - first commit + First commit ---- If you want to send that repository to someone and you don't have access to a repository to push to, or simply don't want to set one up, you can bundle it with `git bundle create`. @@ -60,8 +60,8 @@ Cloning into 'repo'... ... $ cd repo $ git log --oneline -9a466c5 second commit -b1ec324 first commit +9a466c5 Second commit +b1ec324 First commit ---- If you don't include HEAD in the references, you have to also specify `-b master` or whatever branch is included because otherwise it won't know what branch to check out. @@ -71,28 +71,28 @@ Now let's say you do three commits on it and want to send the new commits back v [source,console] ---- $ git log --oneline -71b84da last commit - second repo -c99cf5b fourth commit - second repo -7011d3d third commit - second repo -9a466c5 second commit -b1ec324 first commit +71b84da Last commit - second repo +c99cf5b Fourth commit - second repo +7011d3d Third commit - second repo +9a466c5 Second commit +b1ec324 First commit ---- First we need to determine the range of commits we want to include in the bundle. Unlike the network protocols which figure out the minimum set of data to transfer over the network for us, we'll have to figure this out manually. - Now, you could just do the same thing and bundle the entire repository, which will work, but it's better to just bundle up the difference - just the three commits we just made locally. +Now, you could just do the same thing and bundle the entire repository, which will work, but it's better to just bundle up the difference - just the three commits we just made locally. In order to do that, you'll have to calculate the difference. As we described in <>, you can specify a range of commits in a number of ways. -To get the three commits that we have in our master branch that weren't in the branch we originally cloned, we can use something like `origin/master..master` or `master ^origin/master`. +To get the three commits that we have in our `master` branch that weren't in the branch we originally cloned, we can use something like `origin/master..master` or `master ^origin/master`. You can test that with the `log` command. [source,console] ---- $ git log --oneline master ^origin/master -71b84da last commit - second repo -c99cf5b fourth commit - second repo -7011d3d third commit - second repo +71b84da Last commit - second repo +c99cf5b Fourth commit - second repo +7011d3d Third commit - second repo ---- So now that we have the list of commits we want to include in the bundle, let's bundle them up. @@ -131,7 +131,7 @@ The `verify` command would have looked like this instead: ---- $ git bundle verify ../commits-bad.bundle error: Repository lacks these prerequisite commits: -error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo +error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 Third commit - second repo ---- However, our first bundle is valid, so we can fetch in commits from it. @@ -145,7 +145,7 @@ $ git bundle list-heads ../commits.bundle The `verify` sub-command will tell you the heads as well. The point is to see what can be pulled in, so you can use the `fetch` or `pull` commands to import commits from this bundle. -Here we'll fetch the 'master' branch of the bundle to a branch named 'other-master' in our repository: +Here we'll fetch the `master` branch of the bundle to a branch named `other-master` in our repository: [source,console] ---- @@ -154,18 +154,18 @@ From ../commits.bundle * [new branch] master -> other-master ---- -Now we can see that we have the imported commits on the 'other-master' branch as well as any commits we've done in the meantime in our own 'master' branch. +Now we can see that we have the imported commits on the `other-master` branch as well as any commits we've done in the meantime in our own `master` branch. [source,console] ---- $ git log --oneline --decorate --graph --all -* 8255d41 (HEAD, master) third commit - first repo -| * 71b84da (other-master) last commit - second repo -| * c99cf5b fourth commit - second repo -| * 7011d3d third commit - second repo +* 8255d41 (HEAD, master) Third commit - first repo +| * 71b84da (other-master) Last commit - second repo +| * c99cf5b Fourth commit - second repo +| * 7011d3d Third commit - second repo |/ -* 9a466c5 second commit -* b1ec324 first commit +* 9a466c5 Second commit +* b1ec324 First commit ---- So, `git bundle` can be really useful for sharing or doing network-type operations when you don't have the proper network or shared repository to do so. diff --git a/book/07-git-tools/sections/credentials.asc b/book/07-git-tools/sections/credentials.asc index 7ff7826a9..7c7bc6ed5 100644 --- a/book/07-git-tools/sections/credentials.asc +++ b/book/07-git-tools/sections/credentials.asc @@ -4,7 +4,7 @@ (((credentials))) (((git commands, credential))) If you use the SSH transport for connecting to remotes, it's possible for you to have a key without a passphrase, which allows you to securely transfer data without typing in your username and password. -However, this isn't possible with the HTTP protocols – every connection needs a username and password. +However, this isn't possible with the HTTP protocols -- every connection needs a username and password. This gets even harder for systems with two-factor authentication, where the token you use for a password is randomly generated and unpronounceable. Fortunately, Git has a credentials system that can help with this. @@ -12,16 +12,17 @@ Git has a few options provided in the box: * The default is not to cache at all. Every connection will prompt you for your username and password. -* The ``cache'' mode keeps credentials in memory for a certain period of time. +* The "`cache`" mode keeps credentials in memory for a certain period of time. None of the passwords are ever stored on disk, and they are purged from the cache after 15 minutes. -* The ``store'' mode saves the credentials to a plain-text file on disk, and they never expire. +* The "`store`" mode saves the credentials to a plain-text file on disk, and they never expire. This means that until you change your password for the Git host, you won't ever have to type in your credentials again. The downside of this approach is that your passwords are stored in cleartext in a plain file in your home directory. -* If you're using a Mac, Git comes with an ``osxkeychain'' mode, which caches credentials in the secure keychain that's attached to your system account. +* If you're using macOS, Git comes with an "`osxkeychain`" mode, which caches credentials in the secure keychain that's attached to your system account. This method stores the credentials on disk, and they never expire, but they're encrypted with the same system that stores HTTPS certificates and Safari auto-fills. -* If you're using Windows, you can install a helper called ``Git Credential Manager for Windows.'' - This is similar to the ``osxkeychain'' helper described above, but uses the Windows Credential Store to control sensitive information. - It can be found at https://github.com/Microsoft/Git-Credential-Manager-for-Windows[]. +* If you're using Windows, you can enable the *Git Credential Manager* feature when installing https://gitforwindows.org/[Git for Windows] or separately install https://github.com/git-ecosystem/git-credential-manager/releases/latest[the latest GCM] as a standalone service. + This is similar to the "`osxkeychain`" helper described above, but uses the Windows Credential Store to control sensitive information. + It can also serve credentials to WSL1 or WSL2. + See https://github.com/git-ecosystem/git-credential-manager#readme[GCM Install Instructions] for more information. You can choose one of these methods by setting a Git configuration value: @@ -31,9 +32,9 @@ $ git config --global credential.helper cache ---- Some of these helpers have options. -The ``store'' helper can take a `--file ` argument, which customizes where the plain-text file is saved (the default is `~/.git-credentials`). -The ``cache'' helper accepts the `--timeout ` option, which changes the amount of time its daemon is kept running (the default is ``900'', or 15 minutes). -Here's an example of how you'd configure the ``store'' helper with a custom file name: +The "`store`" helper can take a `--file ` argument, which customizes where the plain-text file is saved (the default is `~/.git-credentials`). +The "`cache`" helper accepts the `--timeout ` option, which changes the amount of time its daemon is kept running (the default is "`900`", or 15 minutes). +Here's an example of how you'd configure the "`store`" helper with a custom file name: [source,console] ---- @@ -59,7 +60,7 @@ Git's root command for the credential-helper system is `git credential`, which t This might be easier to understand with an example. Let's say that a credential helper has been configured, and the helper has stored credentials for `mygithost`. -Here's a session that uses the ``fill'' command, which is invoked when Git is trying to find credentials for a host: +Here's a session that uses the "`fill`" command, which is invoked when Git is trying to find credentials for a host: [source,console] ---- @@ -103,7 +104,7 @@ There are several forms it can take: |====== So the helpers described above are actually named `git-credential-cache`, `git-credential-store`, and so on, and we can configure them to take command-line arguments. -The general form for this is ``git-credential-foo [args] .'' +The general form for this is "`git-credential-foo [args] .`" The stdin/stdout protocol is the same as git-credential, but they use a slightly different set of actions: * `get` is a request for a username/password pair. @@ -115,7 +116,7 @@ For the `get` action, however, Git is very interested in what the helper has to If the helper doesn't know anything useful, it can simply exit with no output, but if it does know, it should augment the provided information with the information it has stored. The output is treated like a series of assignment statements; anything provided will replace what Git already knows. -Here's the same example from above, but skipping git-credential and going straight for git-credential-store: +Here's the same example from above, but skipping `git-credential` and going straight for `git-credential-store`: [source,console] ---- @@ -132,7 +133,7 @@ username=bob <3> password=s3cre7 ---- -<1> Here we tell `git-credential-store` to save some credentials: the username ``bob'' and the password ``s3cre7'' are to be used when `https://mygithost` is accessed. +<1> Here we tell `git-credential-store` to save some credentials: the username "`bob`" and the password "`s3cre7`" are to be used when `https://mygithost` is accessed. <2> Now we'll retrieve those credentials. We provide the parts of the connection we already know (`https://mygithost`), and an empty line. <3> `git-credential-store` replies with the username and password we stored above. @@ -164,9 +165,9 @@ Once again, we'll write this extension in Ruby, but any language will work so lo Here's the full source code of our new credential helper: [source,ruby] --------- +---- include::../git-credential-read-only[] --------- +---- <1> Here we parse the command-line options, allowing the user to specify the input file. The default is `~/.git-credentials`. @@ -174,7 +175,7 @@ include::../git-credential-read-only[] <3> This loop reads from stdin until the first blank line is reached. The inputs are stored in the `known` hash for later reference. <4> This loop reads the contents of the storage file, looking for matches. - If the protocol and host from `known` match this line, the program prints the results to stdout and exits. + If the protocol, host, and username from `known` match this line, the program prints the results to stdout and exits. We'll save our helper as `git-credential-read-only`, put it somewhere in our `PATH` and mark it executable. Here's what an interactive session looks like: @@ -184,6 +185,7 @@ Here's what an interactive session looks like: $ git credential-read-only --file=/mnt/shared/creds get protocol=https host=mygithost +username=bob protocol=https host=mygithost @@ -191,7 +193,7 @@ username=bob password=s3cre7 ---- -Since its name starts with ``git-'', we can use the simple syntax for the configuration value: +Since its name starts with "`git-`", we can use the simple syntax for the configuration value: [source,console] ---- diff --git a/book/07-git-tools/sections/debugging.asc b/book/07-git-tools/sections/debugging.asc index 018b50541..dd615c1c7 100644 --- a/book/07-git-tools/sections/debugging.asc +++ b/book/07-git-tools/sections/debugging.asc @@ -85,7 +85,7 @@ $ git bisect start $ git bisect bad $ git bisect good v1.0 Bisecting: 6 revisions left to test after this -[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo +[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] Error handling on repo ---- Git figured out that about 12 commits came between the commit you marked as the last good commit (v1.0) and the current bad version, and it checked out the middle one for you. @@ -97,7 +97,7 @@ It turns out there is no issue here, and you tell Git that by typing `git bisect ---- $ git bisect good Bisecting: 3 revisions left to test after this -[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing +[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] Secure this thing ---- Now you're on another commit, halfway between the one you just tested and your bad commit. @@ -107,11 +107,11 @@ You run your test again and find that this commit is broken, so you tell Git tha ---- $ git bisect bad Bisecting: 1 revisions left to test after this -[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table +[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] Drop exceptions table ---- This commit is fine, and now Git has all the information it needs to determine where the issue was introduced. -It tells you the SHA-1 of the first bad commit and show some of the commit information and which files were modified in that commit so you can figure out what happened that may have introduced this bug: +It tells you the SHA-1 of the first bad commit and shows some of the commit information and which files were modified in that commit so you can figure out what happened that may have introduced this bug: [source,console] ---- @@ -121,7 +121,7 @@ commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett Date: Tue Jan 27 14:48:32 2009 -0800 - secure this thing + Secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config diff --git a/book/07-git-tools/sections/interactive-staging.asc b/book/07-git-tools/sections/interactive-staging.asc index affa704b2..1f7a5635d 100644 --- a/book/07-git-tools/sections/interactive-staging.asc +++ b/book/07-git-tools/sections/interactive-staging.asc @@ -24,7 +24,7 @@ What now> You can see that this command shows you a much different view of your staging area than you're probably used to -- basically, the same information you get with `git status` but a bit more succinct and informative. It lists the changes you've staged on the left and unstaged changes on the right. -After this comes a ``Commands'' section, which allows you to do a number of things like staging and unstaging files, staging parts of files, adding untracked files, and displaying diffs of what has been staged. +After this comes a "`Commands`" section, which allows you to do a number of things like staging and unstaging files, staging parts of files, adding untracked files, and displaying diffs of what has been staged. ==== Staging and Unstaging Files diff --git a/book/07-git-tools/sections/replace.asc b/book/07-git-tools/sections/replace.asc index 95cf842a2..fd7c8ecd4 100644 --- a/book/07-git-tools/sections/replace.asc +++ b/book/07-git-tools/sections/replace.asc @@ -18,33 +18,35 @@ We'll use a simple repository with five simple commits: [source,console] ---- $ git log --oneline -ef989d8 fifth commit -c6e1e95 fourth commit -9c68fdc third commit -945704c second commit -c1822cf first commit +ef989d8 Fifth commit +c6e1e95 Fourth commit +9c68fdc Third commit +945704c Second commit +c1822cf First commit ---- We want to break this up into two lines of history. One line goes from commit one to commit four - that will be the historical one. The second line will just be commits four and five - that will be the recent history. -image::images/replace1.png[] +.Example Git history +image::images/replace1.png[Example Git history] -Well, creating the historical history is easy, we can just put a branch in the history and then push that branch to the master branch of a new remote repository. +Well, creating the historical history is easy, we can just put a branch in the history and then push that branch to the `master` branch of a new remote repository. [source,console] ---- $ git branch history c6e1e95 $ git log --oneline --decorate -ef989d8 (HEAD, master) fifth commit -c6e1e95 (history) fourth commit -9c68fdc third commit -945704c second commit -c1822cf first commit +ef989d8 (HEAD, master) Fifth commit +c6e1e95 (history) Fourth commit +9c68fdc Third commit +945704c Second commit +c1822cf First commit ---- -image::images/replace2.png[] +.Creating a new `history` branch +image::images/replace2.png[Creating a new `history` branch] Now we can push the new `history` branch to the `master` branch of our new repository: @@ -69,11 +71,11 @@ We need an overlap so we can replace a commit in one with an equivalent commit i [source,console] ---- $ git log --oneline --decorate -ef989d8 (HEAD, master) fifth commit -c6e1e95 (history) fourth commit -9c68fdc third commit -945704c second commit -c1822cf first commit +ef989d8 (HEAD, master) Fifth commit +c6e1e95 (history) Fourth commit +9c68fdc Third commit +945704c Second commit +c1822cf First commit ---- It's useful in this case to create a base commit that has instructions on how to expand the history, so other developers know what to do if they hit the first commit in the truncated history and need more. @@ -85,7 +87,7 @@ We can create our base commit using the `commit-tree` command, which just takes [source,console] ---- -$ echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree} +$ echo 'Get history from blah blah blah' | git commit-tree 9c68fdc^{tree} 622e88e9cbfbacfb75b5279245b9fb38dfea10cf ---- @@ -94,10 +96,11 @@ $ echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree} The `commit-tree` command is one of a set of commands that are commonly referred to as 'plumbing' commands. These are commands that are not generally meant to be used directly, but instead are used by *other* Git commands to do smaller jobs. On occasions when we're doing weirder things like this, they allow us to do really low-level things but are not meant for daily use. -You can read more about plumbing commands in <> +You can read more about plumbing commands in <>. ===== -image::images/replace3.png[] +.Creating a base commit using `commit-tree` +image::images/replace3.png[Creating a base commit using `commit-tree`] OK, so now that we have a base commit, we can rebase the rest of our history on top of that with `git rebase --onto`. The `--onto` argument will be the SHA-1 we just got back from `commit-tree` and the rebase point will be the third commit (the parent of the first commit we want to keep, `9c68fdc`): @@ -110,7 +113,8 @@ Applying: fourth commit Applying: fifth commit ---- -image::images/replace4.png[] +.Rebasing the history on top of the base commit +image::images/replace4.png[Rebasing the history on top of the base commit] OK, so now we've re-written our recent history on top of a throw away base commit that now has instructions in it on how to reconstitute the entire history if we wanted to. We can push that new history to a new project and now when people clone that repository, they will only see the most recent two commits and then a base commit with instructions. @@ -124,9 +128,9 @@ $ git clone https://github.com/schacon/project $ cd project $ git log --oneline master -e146b5f fifth commit -81a708d fourth commit -622e88e get history from blah blah blah +e146b5f Fifth commit +81a708d Fourth commit +622e88e Get history from blah blah blah $ git remote add project-history https://github.com/schacon/project-history $ git fetch project-history @@ -139,19 +143,19 @@ Now the collaborator would have their recent commits in the `master` branch and [source,console] ---- $ git log --oneline master -e146b5f fifth commit -81a708d fourth commit -622e88e get history from blah blah blah +e146b5f Fifth commit +81a708d Fourth commit +622e88e Get history from blah blah blah $ git log --oneline project-history/master -c6e1e95 fourth commit -9c68fdc third commit -945704c second commit -c1822cf first commit +c6e1e95 Fourth commit +9c68fdc Third commit +945704c Second commit +c1822cf First commit ---- To combine them, you can simply call `git replace` with the commit you want to replace and then the commit you want to replace it with. -So we want to replace the "fourth" commit in the master branch with the "fourth" commit in the `project-history/master` branch: +So we want to replace the "fourth" commit in the `master` branch with the "fourth" commit in the `project-history/master` branch: [source,console] ---- @@ -163,16 +167,17 @@ Now, if you look at the history of the `master` branch, it appears to look like [source,console] ---- $ git log --oneline master -e146b5f fifth commit -81a708d fourth commit -9c68fdc third commit -945704c second commit -c1822cf first commit +e146b5f Fifth commit +81a708d Fourth commit +9c68fdc Third commit +945704c Second commit +c1822cf First commit ---- Cool, right? Without having to change all the SHA-1s upstream, we were able to replace one commit in our history with an entirely different commit and all the normal tools (`bisect`, `blame`, etc) will work how we would expect them to. -image::images/replace5.png[] +.Combining the commits with `git replace` +image::images/replace5.png[Combining the commits with `git replace`] Interestingly, it still shows `81a708d` as the SHA-1, even though it's actually using the `c6e1e95` commit data that we replaced it with. Even if you run a command like `cat-file`, it will show you the replaced data: diff --git a/book/07-git-tools/sections/rerere.asc b/book/07-git-tools/sections/rerere.asc index a030104c3..dd3e60ea4 100644 --- a/book/07-git-tools/sections/rerere.asc +++ b/book/07-git-tools/sections/rerere.asc @@ -2,7 +2,7 @@ === Rerere The `git rerere` functionality is a bit of a hidden feature. -The name stands for ``reuse recorded resolution'' and, as the name implies, it allows you to ask Git to remember how you've resolved a hunk conflict so that the next time it sees the same conflict, Git can resolve it for you automatically. +The name stands for "`reuse recorded resolution`" and, as the name implies, it allows you to ask Git to remember how you've resolved a hunk conflict so that the next time it sees the same conflict, Git can resolve it for you automatically. There are a number of scenarios in which this functionality might be really handy. One of the examples that is mentioned in the documentation is when you want to make sure a long-lived topic branch will ultimately merge cleanly, but you don't want to have a bunch of intermediate merge commits cluttering up your commit history. @@ -36,9 +36,10 @@ def hello end ---- -In one branch we change the word ``hello'' to ``hola'', then in another branch we change the ``world'' to ``mundo'', just like before. +In one branch we change the word "`hello`" to "`hola`", then in another branch we change the "`world`" to "`mundo`", just like before. -image::images/rerere1.png[] +.Two branches changing the same part of the same file differently +image::images/rerere1.png[Two branches changing the same part of the same file differently] When we merge the two branches together, we'll get a merge conflict: @@ -129,7 +130,7 @@ $ git rerere diff end ---- -So that basically says, when Git sees a hunk conflict in a `hello.rb` file that has ``hello mundo'' on one side and ``hola world'' on the other, it will resolve it to ``hola mundo''. +So that basically says, when Git sees a hunk conflict in a `hello.rb` file that has "`hello mundo`" on one side and "`hola world`" on the other, it will resolve it to "`hola mundo`". Now we can mark it as resolved and commit it: @@ -143,9 +144,10 @@ Recorded resolution for 'hello.rb'. You can see that it "Recorded resolution for FILE". -image::images/rerere2.png[] +.Recorded resolution for FILE +image::images/rerere2.png[Recorded resolution for FILE] -Now, let's undo that merge and then rebase it on top of our master branch instead. +Now, let's undo that merge and then rebase it on top of our `master` branch instead. We can move our branch back by using `git reset` as we saw in <>. [source,console] @@ -205,7 +207,8 @@ index a440db6,54336ba..0000000 end ---- -image::images/rerere3.png[] +.Automatically resolved merge conflict using previous resolution +image::images/rerere3.png[Automatically resolved merge conflict using previous resolution] You can also recreate the conflicted file state with `git checkout`: @@ -249,4 +252,4 @@ $ git rebase --continue Applying: i18n one word ---- -So, if you do a lot of re-merges, or want to keep a topic branch up to date with your master branch without a ton of merges, or you rebase often, you can turn on `rerere` to help your life out a bit. +So, if you do a lot of re-merges, or want to keep a topic branch up to date with your `master` branch without a ton of merges, or you rebase often, you can turn on `rerere` to help your life out a bit. diff --git a/book/07-git-tools/sections/reset.asc b/book/07-git-tools/sections/reset.asc index 17962c60a..f5b953417 100644 --- a/book/07-git-tools/sections/reset.asc +++ b/book/07-git-tools/sections/reset.asc @@ -9,8 +9,8 @@ For this, we recommend a simple metaphor. ==== The Three Trees An easier way to think about `reset` and `checkout` is through the mental frame of Git being a content manager of three different trees. -By ``tree'' here, we really mean ``collection of files'', not specifically the data structure. -(There are a few cases where the index doesn't exactly act like a tree, but for our purposes it is easier to think about it this way for now.) +By "`tree`" here, we really mean "`collection of files`", not specifically the data structure. +There are a few cases where the index doesn't exactly act like a tree, but for our purposes it is easier to think about it this way for now. Git as a system manages and manipulates three trees in its normal operation: @@ -46,13 +46,13 @@ $ git ls-tree -r HEAD 040000 tree 99f1a6d12cb4b6f19... lib ---- -The Git `cat-file` and `ls-tree` commands are ``plumbing'' commands that are used for lower level things and not really used in day-to-day work, but they help us see what's going on here. +The Git `cat-file` and `ls-tree` commands are "`plumbing`" commands that are used for lower level things and not really used in day-to-day work, but they help us see what's going on here. [[_the_index]] ===== The Index The _index_ is your *proposed next commit*. -We've also been referring to this concept as Git's ``Staging Area'' as this is what Git looks at when you run `git commit`. +We've also been referring to this concept as Git's "`Staging Area`" as this is what Git looks at when you run `git commit`. Git populates this index with a list of all the file contents that were last checked out into your working directory and what they looked like when they were originally checked out. You then replace some of those files with new versions of them, and `git commit` converts that into the tree for a new commit. @@ -71,7 +71,7 @@ The index is not technically a tree structure -- it's actually implemented as a ===== The Working Directory -Finally, you have your _working directory_ (also commonly referred to as the ``working tree''). +Finally, you have your _working directory_ (also commonly referred to as the "`working tree`"). The other two trees store their content in an efficient but inconvenient manner, inside the `.git` folder. The working directory unpacks them into actual files, which makes it much easier for you to edit them. Think of the working directory as a *sandbox*, where you can try changes out before committing them to your staging area (index) and then to history. @@ -92,23 +92,27 @@ $ tree Git's typical workflow is to record snapshots of your project in successively better states, by manipulating these three trees. -image::images/reset-workflow.png[] +.Git's typical workflow +image::images/reset-workflow.png[Git's typical workflow] Let's visualize this process: say you go into a new directory with a single file in it. We'll call this *v1* of the file, and we'll indicate it in blue. -Now we run `git init`, which will create a Git repository with a HEAD reference which points to an unborn branch (`master` doesn't exist yet). +Now we run `git init`, which will create a Git repository with a HEAD reference which points to the unborn `master` branch. -image::images/reset-ex1.png[] +.Newly-initialized Git repository with unstaged file in the working directory +image::images/reset-ex1.png[Newly-initialized Git repository with unstaged file in the working directory] At this point, only the working directory tree has any content. Now we want to commit this file, so we use `git add` to take content in the working directory and copy it to the index. -image::images/reset-ex2.png[] +.File is copied to index on `git add` +image::images/reset-ex2.png[File is copied to index on `git add`] Then we run `git commit`, which takes the contents of the index and saves it as a permanent snapshot, creates a commit object which points to that snapshot, and updates `master` to point to that commit. -image::images/reset-ex3.png[] +.The `git commit` step +image::images/reset-ex3.png[The `git commit` step] If we run `git status`, we'll see no changes, because all three trees are the same. @@ -116,22 +120,25 @@ Now we want to make a change to that file and commit it. We'll go through the same process; first, we change the file in our working directory. Let's call this *v2* of the file, and indicate it in red. -image::images/reset-ex4.png[] +.Git repository with changed file in the working directory +image::images/reset-ex4.png[Git repository with changed file in the working directory] -If we run `git status` right now, we'll see the file in red as ``Changes not staged for commit,'' because that entry differs between the index and the working directory. +If we run `git status` right now, we'll see the file in red as "`Changes not staged for commit`", because that entry differs between the index and the working directory. Next we run `git add` on it to stage it into our index. -image::images/reset-ex5.png[] +.Staging change to index +image::images/reset-ex5.png[Staging change to index] -At this point, if we run `git status`, we will see the file in green under ``Changes to be committed'' because the index and HEAD differ -- that is, our proposed next commit is now different from our last commit. +At this point, if we run `git status`, we will see the file in green under "`Changes to be committed`" because the index and HEAD differ -- that is, our proposed next commit is now different from our last commit. Finally, we run `git commit` to finalize the commit. -image::images/reset-ex6.png[] +.The `git commit` step with changed file +image::images/reset-ex6.png[The `git commit` step with changed file] Now `git status` will give us no output, because all three trees are the same again. Switching branches or cloning goes through a similar process. -When you checkout a branch, it changes *HEAD* to point to the new branch ref, populates your *index* with the snapshot of that commit, then copies the contents of the *index* into your *working Directory*. +When you checkout a branch, it changes *HEAD* to point to the new branch ref, populates your *index* with the snapshot of that commit, then copies the contents of the *index* into your *working directory*. ==== The Role of Reset @@ -140,7 +147,8 @@ The `reset` command makes more sense when viewed in this context. For the purposes of these examples, let's say that we've modified `file.txt` again and committed it a third time. So now our history looks like this: -image::images/reset-start.png[] +.Git repository with three commits +image::images/reset-start.png[Git repository with three commits] Let's now walk through exactly what `reset` does when you call it. It directly manipulates these three trees in a simple and predictable way. @@ -152,7 +160,8 @@ The first thing `reset` will do is move what HEAD points to. This isn't the same as changing HEAD itself (which is what `checkout` does); `reset` moves the branch that HEAD is pointing to. This means if HEAD is set to the `master` branch (i.e. you're currently on the `master` branch), running `git reset 9e5e6a4` will start by making `master` point to `9e5e6a4`. -image::images/reset-soft.png[] +.Soft reset +image::images/reset-soft.png[Soft reset] No matter what form of `reset` with a commit you invoke, this is the first thing it will always try to do. With `reset --soft`, it will simply stop there. @@ -162,13 +171,14 @@ When you run `git commit`, Git creates a new commit and moves the branch that HE When you `reset` back to `HEAD~` (the parent of HEAD), you are moving the branch back to where it was, without changing the index or working directory. You could now update the index and run `git commit` again to accomplish what `git commit --amend` would have done (see <<_git_amend>>). -===== Step 2: Updating the Index (--mixed) +===== Step 2: Updating the Index (`--mixed`) Note that if you run `git status` now you'll see in green the difference between the index and what the new HEAD is. The next thing `reset` will do is to update the index with the contents of whatever snapshot HEAD now points to. -image::images/reset-mixed.png[] +.Mixed reset +image::images/reset-mixed.png[Mixed reset] If you specify the `--mixed` option, `reset` will stop at this point. This is also the default, so if you specify no option at all (just `git reset HEAD~` in this case), this is where the command will stop. @@ -176,12 +186,13 @@ This is also the default, so if you specify no option at all (just `git reset HE Now take another second to look at that diagram and realize what happened: it still undid your last `commit`, but also _unstaged_ everything. You rolled back to before you ran all your `git add` and `git commit` commands. -===== Step 3: Updating the Working Directory (--hard) +===== Step 3: Updating the Working Directory (`--hard`) The third thing that `reset` will do is to make the working directory look like the index. If you use the `--hard` option, it will continue to this stage. -image::images/reset-hard.png[] +.Hard reset +image::images/reset-hard.png[Hard reset] So let's think about what just happened. You undid your last commit, the `git add` and `git commit` commands, *and* all the work you did in your working directory. @@ -194,9 +205,9 @@ In this particular case, we still have the *v3* version of our file in a commit The `reset` command overwrites these three trees in a specific order, stopping when you tell it to: -1. Move the branch HEAD points to _(stop here if `--soft`)_ -2. Make the index look like HEAD _(stop here unless `--hard`)_ -3. Make the working directory look like the index +1. Move the branch HEAD points to _(stop here if `--soft`)_. +2. Make the index look like HEAD _(stop here unless `--hard`)_. +3. Make the working directory look like the index. ==== Reset With a Path @@ -208,25 +219,27 @@ But the index and working directory _can_ be partially updated, so reset proceed So, assume we run `git reset file.txt`. This form (since you did not specify a commit SHA-1 or branch, and you didn't specify `--soft` or `--hard`) is shorthand for `git reset --mixed HEAD file.txt`, which will: -1. Move the branch HEAD points to _(skipped)_ -2. Make the index look like HEAD _(stop here)_ +1. Move the branch HEAD points to _(skipped)_. +2. Make the index look like HEAD _(stop here)_. So it essentially just copies `file.txt` from HEAD to the index. -image::images/reset-path1.png[] +.Mixed reset with a path +image::images/reset-path1.png[Mixed reset with a path] This has the practical effect of _unstaging_ the file. If we look at the diagram for that command and think about what `git add` does, they are exact opposites. -image::images/reset-path2.png[] +.Staging file to index +image::images/reset-path2.png[Staging file to index] -This is why the output of the `git status` command suggests that you run this to unstage a file. -(See <> for more on this.) +This is why the output of the `git status` command suggests that you run this to unstage a file (see <> for more on this). -We could just as easily not let Git assume we meant ``pull the data from HEAD'' by specifying a specific commit to pull that file version from. +We could just as easily not let Git assume we meant "`pull the data from HEAD`" by specifying a specific commit to pull that file version from. We would just run something like `git reset eb43bf file.txt`. -image::images/reset-path3.png[] +.Soft reset with a path to a specific commit +image::images/reset-path3.png[Soft reset with a path to a specific commit] This effectively does the same thing as if we had reverted the content of the file to *v1* in the working directory, ran `git add` on it, then reverted it back to *v3* again (without actually going through all those steps). If we run `git commit` now, it will record a change that reverts that file back to *v1*, even though we never actually had it in our working directory again. @@ -238,25 +251,28 @@ So you can selectively unstage or revert content. Let's look at how to do something interesting with this newfound power -- squashing commits. -Say you have a series of commits with messages like ``oops.'', ``WIP'' and ``forgot this file''. +Say you have a series of commits with messages like "`oops.`", "`WIP`" and "`forgot this file`". You can use `reset` to quickly and easily squash them into a single commit that makes you look really smart. -(<<_squashing>> shows another way to do this, but in this example it's simpler to use `reset`.) +<<_squashing>> shows another way to do this, but in this example it's simpler to use `reset`. Let's say you have a project where the first commit has one file, the second commit added a new file and changed the first, and the third commit changed the first file again. The second commit was a work in progress and you want to squash it down. -image::images/reset-squash-r1.png[] +.Git repository +image::images/reset-squash-r1.png[Git repository] You can run `git reset --soft HEAD~2` to move the HEAD branch back to an older commit (the most recent commit you want to keep): -image::images/reset-squash-r2.png[] +.Moving HEAD with soft reset +image::images/reset-squash-r2.png[Moving HEAD with soft reset] And then simply run `git commit` again: -image::images/reset-squash-r3.png[] +.Git repository with squashed commit +image::images/reset-squash-r3.png[Git repository with squashed commit] -Now you can see that your reachable history, the history you would push, now looks like you had one commit with `file-a.txt` v1, then a second that both modified `file-a.txt` to v3 and added `file-b.txt`. -The commit with the v2 version of the file is no longer in the history. +Now you can see that your reachable history, the history you would push, now looks like you had one commit with `file-a.txt` *v1*, then a second that both modified `file-a.txt` to *v3* and added `file-b.txt`. +The commit with the *v2* version of the file is no longer in the history. ==== Check It Out @@ -282,7 +298,8 @@ HEAD will now point to `master`. So, in both cases we're moving HEAD to point to commit A, but _how_ we do so is very different. `reset` will move the branch HEAD points to, `checkout` moves HEAD itself. -image::images/reset-checkout.png[] +.`git checkout` and `git reset` +image::images/reset-checkout.png[`git checkout` and `git reset`] ===== With Paths @@ -297,7 +314,7 @@ Also, like `git reset` and `git add`, `checkout` will accept a `--patch` option Hopefully now you understand and feel more comfortable with the `reset` command, but are probably still a little confused about how exactly it differs from `checkout` and could not possibly remember all the rules of the different invocations. Here's a cheat-sheet for which commands affect which trees. -The ``HEAD'' column reads ``REF'' if that command moves the reference (branch) that HEAD points to, and ``HEAD'' if it moves HEAD itself. +The "`HEAD`" column reads "`REF`" if that command moves the reference (branch) that HEAD points to, and "`HEAD`" if it moves HEAD itself. Pay especial attention to the 'WD Safe?' column -- if it says *NO*, take a second to think before running that command. [options="header", cols="3,1,1,1,1"] diff --git a/book/07-git-tools/sections/revision-selection.asc b/book/07-git-tools/sections/revision-selection.asc index 14fb23736..95e8e8305 100644 --- a/book/07-git-tools/sections/revision-selection.asc +++ b/book/07-git-tools/sections/revision-selection.asc @@ -22,7 +22,7 @@ commit 734713bc047d87bf7eac9674765ae793478c50d3 Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 - fixed refs handling, added gc auto, updated tests + Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd... 35cfb2b... @@ -35,7 +35,7 @@ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 - added some blame and merge stuff + Add some blame and merge stuff ---- In this case, say you're interested in the commit whose hash begins with `1c002dd...`. @@ -54,9 +54,9 @@ If you pass `--abbrev-commit` to the `git log` command, the output will use shor [source,console] ---- $ git log --abbrev-commit --pretty=oneline -ca82a6d changed the version number -085bb3b removed unnecessary test code -a11bef0 first commit +ca82a6d Change the version number +085bb3b Remove unnecessary test code +a11bef0 Initial commit ---- Generally, eight to ten characters are more than enough to be unique within a project. @@ -74,16 +74,16 @@ If you try to check out that object again at some point, you'll always get the d However, you should be aware of how ridiculously unlikely this scenario is. The SHA-1 digest is 20 bytes or 160 bits. -The number of randomly hashed objects needed to ensure a 50% probability of a single collision is about 2^80^ -(the formula for determining collision probability is `p = (n(n-1)/2) * (1/2^160))`. 2^80^ -is 1.2 x 10^24^ -or 1 million billion billion. +The number of randomly hashed objects needed to ensure a 50% probability of a single collision is about 2^80^ (the formula for determining collision probability is `p = (n(n-1)/2) * (1/2^160)`). +2^80^ is 1.2 x 10^24^ or 1 million billion billion. That's 1,200 times the number of grains of sand on the earth. Here's an example to give you an idea of what it would take to get a SHA-1 collision. If all 6.5 billion humans on Earth were programming, and every second, each one was producing code that was the equivalent of the entire Linux kernel history (6.5 million Git objects) and pushing it into one enormous Git repository, it would take roughly 2 years until that repository contained enough objects to have a 50% probability of a single SHA-1 object collision. -Thus, a SHA-1 collision is less likely than every member of your programming team being attacked and killed by wolves in unrelated incidents on the same night. +Thus, an organic SHA-1 collision is less likely than every member of your programming team being attacked and killed by wolves in unrelated incidents on the same night. +If you dedicate several thousands of dollars' worth of computing power to it, it is possible to synthesize two files with the same hash, as proven on https://shattered.io/[^] in February 2017. +Git is moving towards using SHA256 as the default hashing algorithm, which is much more resilient to collision attacks, and has code in place to help mitigate this attack (although it cannot completely eliminate it). ==== [[_branch_references]] @@ -112,16 +112,16 @@ ca82a6dff817ec66f44342007202690a93763949 [[_git_reflog]] ==== RefLog Shortnames -One of the things Git does in the background while you're working away is keep a ``reflog'' -- a log of where your HEAD and branch references have been for the last few months. +One of the things Git does in the background while you're working away is keep a "`reflog`" -- a log of where your HEAD and branch references have been for the last few months. You can see your reflog by using `git reflog`: [source,console] ---- $ git reflog -734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated +734713b HEAD@{0}: commit: Fix refs handling, add gc auto, update tests d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy. -1c002dd HEAD@{2}: commit: added some blame and merge stuff +1c002dd HEAD@{2}: commit: Add some blame and merge stuff 1c36188 HEAD@{3}: rebase -i (squash): updating HEAD 95df984 HEAD@{4}: commit: # This is a combination of two commits. 1c36188 HEAD@{5}: rebase -i (squash): updating HEAD @@ -138,14 +138,14 @@ $ git show HEAD@{5} ---- You can also use this syntax to see where a branch was some specific amount of time ago. -For instance, to see where your `master` branch was yesterday, you can type +For instance, to see where your `master` branch was yesterday, you can type: [source,console] ---- $ git show master@{yesterday} ---- -That would show you where tip of your `master` branch was yesterday. +That would show you where the tip of your `master` branch was yesterday. This technique only works for data that's still in your reflog, so you can't use it to look for commits older than a few months. To see reflog information formatted like the `git log` output, you can run `git log -g`: @@ -155,11 +155,11 @@ To see reflog information formatted like the `git log` output, you can run `git $ git log -g master commit 734713bc047d87bf7eac9674765ae793478c50d3 Reflog: master@{0} (Scott Chacon ) -Reflog message: commit: fixed refs handling, added gc auto, updated +Reflog message: commit: Fix refs handling, add gc auto, update tests Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 - fixed refs handling, added gc auto, updated tests + Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Reflog: master@{1} (Scott Chacon ) @@ -177,7 +177,23 @@ Running `git show HEAD@{2.months.ago}` will show you the matching commit only if [TIP] .Think of the reflog as Git's version of shell history ==== -If you have a UNIX or Linux background, you can think of the reflog as Git's version of shell history, which emphasizes that what's there is clearly relevant only for you and your ``session'', and has nothing to do with anyone else who might be working on the same machine. +If you have a UNIX or Linux background, you can think of the reflog as Git's version of shell history, which emphasizes that what's there is clearly relevant only for you and your "`session`", and has nothing to do with anyone else who might be working on the same machine. +==== + +[NOTE] +.Escaping braces in PowerShell +==== + +When using PowerShell, braces like `{` and `}` are special characters and must be escaped. +You can escape them with a backtick ` or put the commit reference in quotes: + +[source,console] +---- +$ git show HEAD@{0} # will NOT work +$ git show HEAD@`{0`} # OK +$ git show "HEAD@{0}" # OK +---- + ==== ==== Ancestry References @@ -189,17 +205,17 @@ Suppose you look at the history of your project: [source,console] ---- $ git log --pretty=format:'%h %s' --graph -* 734713b fixed refs handling, added gc auto, updated tests +* 734713b Fix refs handling, add gc auto, update tests * d921970 Merge commit 'phedders/rdocs' |\ | * 35cfb2b Some rdoc changes -* | 1c002dd added some blame and merge stuff +* | 1c002dd Add some blame and merge stuff |/ -* 1c36188 ignore *.gem -* 9b29157 add open3_detach to gemspec file list +* 1c36188 Ignore *.gem +* 9b29157 Add open3_detach to gemspec file list ---- -Then, you can see the previous commit by specifying `HEAD^`, which means ``the parent of HEAD'': +Then, you can see the previous commit by specifying `HEAD^`, which means "`the parent of HEAD`": [source,console] ---- @@ -228,7 +244,7 @@ $ git show "HEAD^" # OK ==== -You can also specify a number after the `^` to identify _which_ parent you want; for example, `d921970^2` means ``the second parent of d921970.'' +You can also specify a number after the `^` to identify _which_ parent you want; for example, `d921970^2` means "`the second parent of d921970.`" This syntax is useful only for merge commits, which have more than one parent -- the _first_ parent of a merge commit is from the branch you were on when you merged (frequently `master`), while the _second_ parent of a merge commit is from the branch that was merged (say, `topic`): [source,console] @@ -238,7 +254,7 @@ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 - added some blame and merge stuff + Add some blame and merge stuff $ git show d921970^2 commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548 @@ -251,8 +267,8 @@ Date: Wed Dec 10 22:22:03 2008 +0000 The other main ancestry specification is the `~` (tilde). This also refers to the first parent, so `HEAD~` and `HEAD^` are equivalent. The difference becomes apparent when you specify a number. -`HEAD~2` means ``the first parent of the first parent,'' or ``the grandparent'' -- it traverses the first parents the number of times you specify. -For example, in the history listed earlier, `HEAD~3` would be +`HEAD~2` means "`the first parent of the first parent,`" or "`the grandparent`" -- it traverses the first parents the number of times you specify. +For example, in the history listed earlier, `HEAD~3` would be: [source,console] ---- @@ -261,10 +277,10 @@ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 - ignore *.gem + Ignore *.gem ---- -This can also be written `HEAD~~~`, which again is the first parent of the first parent of the first parent: +This can also be written `HEAD\~~~`, which again is the first parent of the first parent of the first parent: [source,console] ---- @@ -273,7 +289,7 @@ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 - ignore *.gem + Ignore *.gem ---- You can also combine these syntaxes -- you can get the second parent of the previous reference (assuming it was a merge commit) by using `HEAD~3^2`, and so on. @@ -282,7 +298,7 @@ You can also combine these syntaxes -- you can get the second parent of the prev ==== Commit Ranges Now that you can specify individual commits, let's see how to specify ranges of commits. -This is particularly useful for managing your branches -- if you have a lot of branches, you can use range specifications to answer questions such as, ``What work is on this branch that I haven't yet merged into my main branch?'' +This is particularly useful for managing your branches -- if you have a lot of branches, you can use range specifications to answer questions such as, "`What work is on this branch that I haven't yet merged into my main branch?`" ===== Double Dot @@ -291,11 +307,11 @@ This basically asks Git to resolve a range of commits that are reachable from on For example, say you have a commit history that looks like <>. [[double_dot]] -.Example history for range selection. -image::images/double-dot.png[Example history for range selection.] +.Example history for range selection +image::images/double-dot.png[Example history for range selection] Say you want to see what is in your `experiment` branch that hasn't yet been merged into your `master` branch. -You can ask Git to show you a log of just those commits with `master..experiment` -- that means ``all commits reachable from experiment that aren't reachable from master.'' +You can ask Git to show you a log of just those commits with `master..experiment` -- that means "`all commits reachable from `experiment` that aren't reachable from `master`.`" For the sake of brevity and clarity in these examples, the letters of the commit objects from the diagram are used in place of the actual log output in the order that they would display: [source,console] diff --git a/book/07-git-tools/sections/rewriting-history.asc b/book/07-git-tools/sections/rewriting-history.asc index a20a34e34..7fbb06d7f 100644 --- a/book/07-git-tools/sections/rewriting-history.asc +++ b/book/07-git-tools/sections/rewriting-history.asc @@ -56,7 +56,7 @@ $ git commit --amend --no-edit ==== Changing Multiple Commit Messages To modify a commit that is farther back in your history, you must move to more complex tools. -Git doesn't have a modify-history tool, but you can use the rebase tool to rebase a series of commits onto the HEAD they were originally based on instead of moving them to another one. +Git doesn't have a modify-history tool, but you can use the rebase tool to rebase a series of commits onto the HEAD that they were originally based on instead of moving them to another one. With the interactive rebase tool, you can then stop after each commit you want to modify and change the message, add files, or do whatever you wish. You can run rebase interactively by adding the `-i` option to `git rebase`. You must indicate how far back you want to rewrite commits by telling the command which commit to rebase onto. @@ -69,16 +69,16 @@ It may be easier to remember the `~3` because you're trying to edit the last thr $ git rebase -i HEAD~3 ---- -Remember again that this is a rebasing command -- every commit included in the range `HEAD~3..HEAD` will be rewritten, whether you change the message or not. +Remember again that this is a rebasing command -- every commit in the range `HEAD~3..HEAD` with a changed message _and all of its descendants_ will be rewritten. Don't include any commit you've already pushed to a central server -- doing so will confuse other developers by providing an alternate version of the same change. Running this command gives you a list of commits in your text editor that looks something like this: [source,console] ---- -pick f7f3f6d changed my name a bit -pick 310154e updated README formatting and added blame -pick a5f4a0d added cat-file +pick f7f3f6d Change my name a bit +pick 310154e Update README formatting and add blame +pick a5f4a0d Add cat-file # Rebase 710f0f8..a5f4a0d onto 710f0f8 # @@ -113,9 +113,9 @@ If you run a `log`, you see something like this: [source,console] ---- $ git log --pretty=format:"%h %s" HEAD~3..HEAD -a5f4a0d added cat-file -310154e updated README formatting and added blame -f7f3f6d changed my name a bit +a5f4a0d Add cat-file +310154e Update README formatting and add blame +f7f3f6d Change my name a bit ---- Notice the reverse order. @@ -124,14 +124,14 @@ It will start at the commit you specify on the command line (`HEAD~3`) and repla It lists the oldest at the top, rather than the newest, because that's the first one it will replay. You need to edit the script so that it stops at the commit you want to edit. -To do so, change the word `pick' to the word `edit' for each of the commits you want the script to stop after. +To do so, change the word "`pick`" to the word "`edit`" for each of the commits you want the script to stop after. For example, to modify only the third commit message, you change the file to look like this: [source,console] ---- -edit f7f3f6d changed my name a bit -pick 310154e updated README formatting and added blame -pick a5f4a0d added cat-file +edit f7f3f6d Change my name a bit +pick 310154e Update README formatting and add blame +pick a5f4a0d Add cat-file ---- When you save and exit the editor, Git rewinds you back to the last commit in that list and drops you on the command line with the following message: @@ -139,7 +139,7 @@ When you save and exit the editor, Git rewinds you back to the last commit in th [source,console] ---- $ git rebase -i HEAD~3 -Stopped at f7f3f6d... changed my name a bit +Stopped at f7f3f6d... Change my name a bit You can amend the commit now, with git commit --amend @@ -150,7 +150,7 @@ Once you're satisfied with your changes, run ---- These instructions tell you exactly what to do. -Type +Type: [source,console] ---- @@ -158,7 +158,7 @@ $ git commit --amend ---- Change the commit message, and exit the editor. -Then, run +Then, run: [source,console] ---- @@ -166,31 +166,31 @@ $ git rebase --continue ---- This command will apply the other two commits automatically, and then you're done. -If you change pick to edit on more lines, you can repeat these steps for each commit you change to edit. +If you change `pick` to `edit` on more lines, you can repeat these steps for each commit you change to `edit`. Each time, Git will stop, let you amend the commit, and continue when you're finished. ==== Reordering Commits You can also use interactive rebases to reorder or remove commits entirely. -If you want to remove the ``added cat-file'' commit and change the order in which the other two commits are introduced, you can change the rebase script from this +If you want to remove the "`Add cat-file`" commit and change the order in which the other two commits are introduced, you can change the rebase script from this: [source,console] ---- -pick f7f3f6d changed my name a bit -pick 310154e updated README formatting and added blame -pick a5f4a0d added cat-file +pick f7f3f6d Change my name a bit +pick 310154e Update README formatting and add blame +pick a5f4a0d Add cat-file ---- to this: [source,console] ---- -pick 310154e updated README formatting and added blame -pick f7f3f6d changed my name a bit +pick 310154e Update README formatting and add blame +pick f7f3f6d Change my name a bit ---- When you save and exit the editor, Git rewinds your branch to the parent of these commits, applies `310154e` and then `f7f3f6d`, and then stops. -You effectively change the order of those commits and remove the ``added cat-file'' commit completely. +You effectively change the order of those commits and remove the "`Add cat-file`" commit completely. [[_squashing]] ==== Squashing Commits @@ -226,14 +226,14 @@ The script puts helpful instructions in the rebase message: # Note that empty commits are commented out ---- -If, instead of ``pick'' or ``edit'', you specify ``squash'', Git applies both that change and the change directly before it and makes you merge the commit messages together. +If, instead of "`pick`" or "`edit`", you specify "`squash`", Git applies both that change and the change directly before it and makes you merge the commit messages together. So, if you want to make a single commit from these three commits, you make the script look like this: [source,console] ---- -pick f7f3f6d changed my name a bit -squash 310154e updated README formatting and added blame -squash a5f4a0d added cat-file +pick f7f3f6d Change my name a bit +squash 310154e Update README formatting and add blame +squash a5f4a0d Add cat-file ---- When you save and exit the editor, Git applies all three changes and then puts you back into the editor to merge the three commit messages: @@ -242,15 +242,15 @@ When you save and exit the editor, Git applies all three changes and then puts y ---- # This is a combination of 3 commits. # The first commit's message is: -changed my name a bit +Change my name a bit # This is the 2nd commit message: -updated README formatting and added blame +Update README formatting and add blame # This is the 3rd commit message: -added cat-file +Add cat-file ---- When you save that, you have a single commit that introduces the changes of all three previous commits. @@ -259,14 +259,14 @@ When you save that, you have a single commit that introduces the changes of all Splitting a commit undoes a commit and then partially stages and commits as many times as commits you want to end up with. For example, suppose you want to split the middle commit of your three commits. -Instead of ``updated README formatting and added blame'', you want to split it into two commits: ``updated README formatting'' for the first, and ``added blame'' for the second. -You can do that in the `rebase -i` script by changing the instruction on the commit you want to split to ``edit'': +Instead of "`Update README formatting and add blame`", you want to split it into two commits: "`Update README formatting`" for the first, and "`Add blame`" for the second. +You can do that in the `rebase -i` script by changing the instruction on the commit you want to split to "`edit`": [source,console] ---- -pick f7f3f6d changed my name a bit -edit 310154e updated README formatting and added blame -pick a5f4a0d added cat-file +pick f7f3f6d Change my name a bit +edit 310154e Update README formatting and add blame +pick a5f4a0d Add cat-file ---- Then, when the script drops you to the command line, you reset that commit, take the changes that have been reset, and create multiple commits out of them. @@ -278,9 +278,9 @@ Now you can stage and commit files until you have several commits, and run `git ---- $ git reset HEAD^ $ git add README -$ git commit -m 'updated README formatting' +$ git commit -m 'Update README formatting' $ git add lib/simplegit.rb -$ git commit -m 'added blame' +$ git commit -m 'Add blame' $ git rebase --continue ---- @@ -289,13 +289,42 @@ Git applies the last commit (`a5f4a0d`) in the script, and your history looks li [source,console] ---- $ git log -4 --pretty=format:"%h %s" -1c002dd added cat-file -9b29157 added blame -35cfb2b updated README formatting -f3cc40e changed my name a bit +1c002dd Add cat-file +9b29157 Add blame +35cfb2b Update README formatting +f7f3f6d Change my name a bit ---- -Once again, this changes the SHA-1s of all the commits in your list, so make sure no commit shows up in that list that you've already pushed to a shared repository. +This changes the SHA-1s of the three most recent commits in your list, so make sure no changed commit shows up in that list that you've already pushed to a shared repository. +Notice that the last commit (`f7f3f6d`) in the list is unchanged. +Despite this commit being shown in the script, because it was marked as "`pick`" and was applied prior to any rebase changes, Git leaves the commit unmodified. + +==== Deleting a commit + +If you want to get rid of a commit, you can delete it using the `rebase -i` script. +In the list of commits, put the word "`drop`" before the commit you want to delete (or just delete that line from the rebase script): + +[source,console] +---- +pick 461cb2a This commit is OK +drop 5aecc10 This commit is broken +---- + +Because of the way Git builds commit objects, deleting or altering a commit will cause the rewriting of all the commits that follow it. +The further back in your repo's history you go, the more commits will need to be recreated. +This can cause lots of merge conflicts if you have many commits later in the sequence that depend on the one you just deleted. + +If you get partway through a rebase like this and decide it's not a good idea, you can always stop. +Type `git rebase --abort`, and your repo will be returned to the state it was in before you started the rebase. + +If you finish a rebase and decide it's not what you want, you can use `git reflog` to recover an earlier version of your branch. +See <> for more information on the `reflog` command. + +[NOTE] +==== +Drew DeVault made a practical hands-on guide with exercises to learn how to use `git rebase`. +You can find it at: https://git-rebase.io/[^] +==== ==== The Nuclear Option: filter-branch @@ -304,6 +333,13 @@ The command is `filter-branch`, and it can rewrite huge swaths of your history, However, it can be very useful. You'll learn a few of the common uses so you can get an idea of some of the things it's capable of. +[CAUTION] +==== +`git filter-branch` has many pitfalls, and is no longer the recommended way to rewrite history. +Instead, consider using `git-filter-repo`, which is a Python script that does a better job for most applications where you would normally turn to `filter-branch`. +Its documentation and source code can be found at https://github.com/newren/git-filter-repo[^]. +==== + [[_removing_file_every_commit]] ===== Removing a File from Every Commit @@ -325,7 +361,7 @@ In this case, you remove a file called `passwords.txt` from every snapshot, whet If you want to remove all accidentally committed editor backup files, you can run something like `git filter-branch --tree-filter 'rm -f *~' HEAD`. You'll be able to watch Git rewriting trees and commits and then move the branch pointer at the end. -It's generally a good idea to do this in a testing branch and then hard-reset your master branch after you've determined the outcome is what you really want. +It's generally a good idea to do this in a testing branch and then hard-reset your `master` branch after you've determined the outcome is what you really want. To run `filter-branch` on all your branches, you can pass `--all` to the command. ===== Making a Subdirectory the New Root diff --git a/book/07-git-tools/sections/searching.asc b/book/07-git-tools/sections/searching.asc index dd025e437..8caf1230f 100644 --- a/book/07-git-tools/sections/searching.asc +++ b/book/07-git-tools/sections/searching.asc @@ -60,7 +60,7 @@ date.c: /* gmtime_r() in match_digit() may have clobbered it */ As you can see, the `gmtime_r` routine is called from both the `match_multi_number` and `match_digit` functions in the `date.c` file (the third match displayed represents just the string appearing in a comment). You can also search for complex combinations of strings with the `--and` flag, which ensures that multiple matches must occur in the same line of text. -For instance, let's look for any lines that define a constant whose name contains _either_ of the substrings ``LINK'' or ``BUF_MAX'', specifically in an older version of the Git codebase represented by the tag `v1.8.0` (we'll throw in the `--break` and `--heading` options which help split up the output into a more readable format): +For instance, let's look for any lines that define a constant whose name contains _either_ of the substrings "`LINK`" or "`BUF_MAX`", specifically in an older version of the Git codebase represented by the tag `v1.8.0` (we'll throw in the `--break` and `--heading` options which help split up the output into a more readable format): [source,console] ---- @@ -96,7 +96,7 @@ As we saw in the above example, we looked for terms in an older version of the G Perhaps you're looking not for _where_ a term exists, but _when_ it existed or was introduced. The `git log` command has a number of powerful tools for finding specific commits by the content of their messages or even the content of the diff they introduce. -If, for example, we want to find out when the `ZLIB_BUF_MAX` constant was originally introduced, we can use the `-S` option (colloquially referred to as the Git ``pickaxe'' option) to tell Git to show us only those commits that changed the number of occurrences of that string. +If, for example, we want to find out when the `ZLIB_BUF_MAX` constant was originally introduced, we can use the `-S` option (colloquially referred to as the Git "`pickaxe`" option) to tell Git to show us only those commits that changed the number of occurrences of that string. [source,console] ---- diff --git a/book/07-git-tools/sections/signing.asc b/book/07-git-tools/sections/signing.asc index f4ce0e38a..0e74b9810 100644 --- a/book/07-git-tools/sections/signing.asc +++ b/book/07-git-tools/sections/signing.asc @@ -29,14 +29,14 @@ Once you have a private key to sign with, you can configure Git to use it for si [source,console] ---- -$ git config --global user.signingkey 0A46826A +$ git config --global user.signingkey 0A46826A! ---- Now Git will use your key by default to sign tags and commits if you want. ==== Signing Tags -If you have a GPG private key setup, you can now use it to sign new tags. +If you have a GPG private key set up, you can now use it to sign new tags. All you have to do is use `-s` instead of `-a`: [source,console] @@ -51,7 +51,7 @@ user: "Ben Straub " If you run `git show` on that tag, you can see your GPG signature attached to it: [source,console] --------- +---- $ git show v1.5 tag v1.5 Tagger: Ben Straub @@ -74,8 +74,8 @@ commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 - changed the version number --------- + Change version number +---- ==== Verifying Tags @@ -117,13 +117,13 @@ If you're interested in signing commits directly instead of just the tags, all y [source,console] ---- -$ git commit -a -S -m 'signed commit' +$ git commit -a -S -m 'Signed commit' You need a passphrase to unlock the secret key for user: "Scott Chacon (Git signing key) " 2048-bit RSA key, ID 0A46826A, created 2014-06-04 -[master 5c3386c] signed commit +[master 5c3386c] Signed commit 4 files changed, 4 insertions(+), 24 deletions(-) rewrite Rakefile (100%) create mode 100644 lib/git.rb @@ -140,7 +140,7 @@ gpg: Good signature from "Scott Chacon (Git signing key) " Author: Scott Chacon Date: Wed Jun 4 19:49:17 2014 -0700 - signed commit + Signed commit ---- Additionally, you can configure `git log` to check any signatures it finds and list them in its output with the `%G?` format. @@ -149,10 +149,10 @@ Additionally, you can configure `git log` to check any signatures it finds and l ---- $ git log --pretty="format:%h %G? %aN %s" -5c3386c G Scott Chacon signed commit -ca82a6d N Scott Chacon changed the version number -085bb3b N Scott Chacon removed unnecessary test code -a11bef0 N Scott Chacon first commit +5c3386c G Scott Chacon Signed commit +ca82a6d N Scott Chacon Change the version number +085bb3b N Scott Chacon Remove unnecessary test code +a11bef0 N Scott Chacon Initial commit ---- Here we can see that only the latest commit is signed and valid and the previous commits are not. @@ -199,5 +199,6 @@ Merge made by the 'recursive' strategy. ==== Everyone Must Sign Signing tags and commits is great, but if you decide to use this in your normal workflow, you'll have to make sure that everyone on your team understands how to do so. +This can be achieved by asking everyone working with the repository to run `git config --local commit.gpgsign true` to automatically have all of their commits in the repository signed by default. If you don't, you'll end up spending a lot of time helping people figure out how to rewrite their commits with signed versions. Make sure you understand GPG and the benefits of signing things before adopting this as part of your standard workflow. diff --git a/book/07-git-tools/sections/stashing-cleaning.asc b/book/07-git-tools/sections/stashing-cleaning.asc index 81b34ea46..7337895c7 100644 --- a/book/07-git-tools/sections/stashing-cleaning.asc +++ b/book/07-git-tools/sections/stashing-cleaning.asc @@ -44,8 +44,8 @@ To push a new stash onto your stack, run `git stash` or `git stash push`: ---- $ git stash Saved working directory and index state \ - "WIP on master: 049d078 added the index file" -HEAD is now at 049d078 added the index file + "WIP on master: 049d078 Create index file" +HEAD is now at 049d078 Create index file (To restore them type "git stash apply") ---- @@ -64,9 +64,9 @@ To see which stashes you've stored, you can use `git stash list`: [source,console] ---- $ git stash list -stash@{0}: WIP on master: 049d078 added the index file -stash@{1}: WIP on master: c264051 Revert "added file_size" -stash@{2}: WIP on master: 21d80a5 added number to log +stash@{0}: WIP on master: 049d078 Create index file +stash@{1}: WIP on master: c264051 Revert "Add file_size" +stash@{2}: WIP on master: 21d80a5 Add number to log ---- In this case, two stashes were saved previously, so you have access to three different stashed works. @@ -114,15 +114,15 @@ Changes not staged for commit: modified: lib/simplegit.rb ---- -The apply option only tries to apply the stashed work -- you continue to have it on your stack. +The `apply` option only tries to apply the stashed work -- you continue to have it on your stack. To remove it, you can run `git stash drop` with the name of the stash to remove: [source,console] ---- $ git stash list -stash@{0}: WIP on master: 049d078 added the index file -stash@{1}: WIP on master: c264051 Revert "added file_size" -stash@{2}: WIP on master: 21d80a5 added number to log +stash@{0}: WIP on master: 049d078 Create index file +stash@{1}: WIP on master: c264051 Revert "Add file_size" +stash@{2}: WIP on master: 21d80a5 Add number to log $ git stash drop stash@{0} Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43) ---- @@ -236,9 +236,9 @@ A safer option is to run `git stash --all` to remove everything but save it in a Assuming you do want to remove cruft files or clean your working directory, you can do so with `git clean`. To remove all the untracked files in your working directory, you can run `git clean -f -d`, which removes any files and also any subdirectories that become empty as a result. -The `-f` means 'force' or ``really do this,'' and is required if the Git configuration variable `clean.requireForce` is not explicitly set to false. +The `-f` means 'force' or "`really do this,`" and is required if the Git configuration variable `clean.requireForce` is not explicitly set to false. -If you ever want to see what it would do, you can run the command with the `--dry-run` (or `-n`) option, which means ``do a dry run and tell me what you _would_ have removed''. +If you ever want to see what it would do, you can run the command with the `--dry-run` (or `-n`) option, which means "`do a dry run and tell me what you _would_ have removed`". [source,console] ---- @@ -249,7 +249,7 @@ Would remove tmp/ By default, the `git clean` command will only remove untracked files that are not ignored. Any file that matches a pattern in your `.gitignore` or other ignore files will not be removed. -If you want to remove those files too, such as to remove all `.o` files generated from a build so you can do a fully clean build, you can add a `-x` to the clean command. +If you want to remove those files too, such as to remove all `.o` files generated from a build so you can do a fully clean build, you can add a `-x` to the `clean` command. [source,console] ---- @@ -269,9 +269,9 @@ Would remove tmp/ ---- If you don't know what the `git clean` command is going to do, always run it with a `-n` first to double check before changing the `-n` to a `-f` and doing it for real. -The other way you can be careful about the process is to run it with the `-i` or ``interactive'' flag. +The other way you can be careful about the process is to run it with the `-i` or "`interactive`" flag. -This will run the clean command in an interactive mode. +This will run the `clean` command in an interactive mode. [source,console] ---- diff --git a/book/07-git-tools/sections/submodules.asc b/book/07-git-tools/sections/submodules.asc index 478f16d7a..188ff6408 100644 --- a/book/07-git-tools/sections/submodules.asc +++ b/book/07-git-tools/sections/submodules.asc @@ -23,7 +23,7 @@ We'll walk through developing a simple project that has been split up into a mai Let's start by adding an existing Git repository as a submodule of the repository that we're working on. To add a new submodule you use the `git submodule add` command with the absolute or relative URL of the project you would like to start tracking. -In this example, we'll add a library called ``DbConnector''. +In this example, we'll add a library called "`DbConnector`". [source,console] ---- @@ -36,7 +36,7 @@ Unpacking objects: 100% (11/11), done. Checking connectivity... done. ---- -By default, submodules will add the subproject into a directory named the same as the repository, in this case ``DbConnector''. +By default, submodules will add the subproject into a directory named the same as the repository, in this case "`DbConnector`". You can add a different path at the end of the command if you want it to go elsewhere. If you run `git status` at this point, you'll notice a few things. @@ -116,8 +116,8 @@ When you commit, you see something like this: [source,console] ---- -$ git commit -am 'added DbConnector module' -[master fb9093c] added DbConnector module +$ git commit -am 'Add DbConnector module' +[master fb9093c] Add DbConnector module 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 DbConnector @@ -166,7 +166,7 @@ $ ---- The `DbConnector` directory is there, but empty. -You must run two commands: `git submodule init` to initialize your local configuration file, and `git submodule update` to fetch all the data from that project and check out the appropriate commit listed in your superproject: +You must run two commands from the main project: `git submodule init` to initialize your local configuration file, and `git submodule update` to fetch all the data from that project and check out the appropriate commit listed in your superproject: [source,console] ---- @@ -185,7 +185,7 @@ Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b2 Now your `DbConnector` subdirectory is at the exact state it was in when you committed earlier. There is another way to do this which is a little simpler, however. -If you pass `--recurse-submodules` to the `git clone` command, it will automatically initialize and update each submodule in the repository. +If you pass `--recurse-submodules` to the `git clone` command, it will automatically initialize and update each submodule in the repository, including nested submodules if any of the submodules in the repository have submodules themselves. [source,console] ---- @@ -206,11 +206,14 @@ Checking connectivity... done. Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc' ---- +If you already cloned the project and forgot `--recurse-submodules`, you can combine the `git submodule init` and `git submodule update` steps by running `git submodule update --init`. +To also initialize, fetch and checkout any nested submodules, you can use the foolproof `git submodule update --init --recursive`. + ==== Working on a Project with Submodules Now we have a copy of a project with submodules in it and will collaborate with our teammates on both the main project and the submodule project. -===== Pulling in Upstream Changes +===== Pulling in Upstream Changes from the Submodule Remote The simplest model of using submodules in a project would be if you were simply consuming a subproject and wanted to get updates from it from time to time but were not actually modifying anything in your checkout. Let's walk through a simple example there. @@ -231,7 +234,7 @@ Fast-forward ---- Now if you go back into the main project and run `git diff --submodule` you can see that the submodule was updated and get a list of commits that were added to it. -If you don't want to type `--submodule` every time you run `git diff`, you can set it as the default format by setting the `diff.submodule` config value to ``log''. +If you don't want to type `--submodule` every time you run `git diff`, you can set it as the default format by setting the `diff.submodule` config value to "`log`". [source,console] ---- @@ -259,9 +262,9 @@ From https://github.com/chaconinc/DbConnector Submodule path 'DbConnector': checked out 'd0354fc054692d3906c85c3af05ddce39a1c0644' ---- -This command will by default assume that you want to update the checkout to the `master` branch of the submodule repository. +This command will by default assume that you want to update the checkout to the default branch of the remote submodule repository (the one pointed to by `HEAD` on the remote). You can, however, set this to something different if you want. -For example, if you want to have the DbConnector submodule track that repository's ``stable'' branch, you can set it in either your `.gitmodules` file (so everyone else also tracks it), or just in your local `.git/config` file. +For example, if you want to have the `DbConnector` submodule track that repository's "`stable`" branch, you can set it in either your `.gitmodules` file (so everyone else also tracks it), or just in your local `.git/config` file. Let's set it in the `.gitmodules` file: [source,console] @@ -280,7 +283,7 @@ Submodule path 'DbConnector': checked out 'c87d55d4c6d4b05ee34fbc8cb6f7bf4585ae6 If you leave off the `-f .gitmodules` it will only make the change for you, but it probably makes more sense to track that information with the repository so everyone else does as well. -When we run `git status` at this point, Git will show us that we have ``new commits'' on the submodule. +When we run `git status` at this point, Git will show us that we have "`new commits`" on the submodule. [source,console] ---- @@ -370,7 +373,84 @@ Submodule DbConnector c3f01dc..c87d55d: > better connection routine ---- -Git will by default try to update *all* of your submodules when you run `git submodule update --remote` so if you have a lot of them, you may want to pass the name of just the submodule you want to try to update. +Git will by default try to update *all* of your submodules when you run `git submodule update --remote`. +If you have a lot of them, you may want to pass the name of just the submodule you want to try to update. + +===== Pulling Upstream Changes from the Project Remote + +Let's now step into the shoes of your collaborator, who has their own local clone of the MainProject repository. +Simply executing `git pull` to get your newly committed changes is not enough: + +[source,console] +---- +$ git pull +From https://github.com/chaconinc/MainProject + fb9093c..0a24cfc master -> origin/master +Fetching submodule DbConnector +From https://github.com/chaconinc/DbConnector + c3f01dc..c87d55d stable -> origin/stable +Updating fb9093c..0a24cfc +Fast-forward + .gitmodules | 2 +- + DbConnector | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +$ git status + On branch master +Your branch is up-to-date with 'origin/master'. +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git checkout -- ..." to discard changes in working directory) + + modified: DbConnector (new commits) + +Submodules changed but not updated: + +* DbConnector c87d55d...c3f01dc (4): + < catch non-null terminated lines + < more robust error handling + < more efficient db routine + < better connection routine + +no changes added to commit (use "git add" and/or "git commit -a") +---- + +By default, the `git pull` command recursively fetches submodules changes, as we can see in the output of the first command above. +However, it does not *update* the submodules. +This is shown by the output of the `git status` command, which shows the submodule is "`modified`", and has "`new commits`". +What's more, the brackets showing the new commits point left (<), indicating that these commits are recorded in MainProject but are not present in the local `DbConnector` checkout. +To finalize the update, you need to run `git submodule update`: + +[source,console] +---- +$ git submodule update --init --recursive +Submodule path 'vendor/plugins/demo': checked out '48679c6302815f6c76f1fe30625d795d9e55fc56' + +$ git status + On branch master +Your branch is up-to-date with 'origin/master'. +nothing to commit, working tree clean +---- + +Note that to be on the safe side, you should run `git submodule update` with the `--init` flag in case the MainProject commits you just pulled added new submodules, and with the `--recursive` flag if any submodules have nested submodules. + +If you want to automate this process, you can add the `--recurse-submodules` flag to the `git pull` command (since Git 2.14). +This will make Git run `git submodule update` right after the pull, putting the submodules in the correct state. +Moreover, if you want to make Git always pull with `--recurse-submodules`, you can set the configuration option `submodule.recurse` to `true` (this works for `git pull` since Git 2.15). +This option will make Git use the `--recurse-submodules` flag for all commands that support it (except `clone`). + +There is a special situation that can happen when pulling superproject updates: it could be that the upstream repository has changed the URL of the submodule in the `.gitmodules` file in one of the commits you pull. +This can happen for example if the submodule project changes its hosting platform. +In that case, it is possible for `git pull --recurse-submodules`, or `git submodule update`, to fail if the superproject references a submodule commit that is not found in the submodule remote locally configured in your repository. +In order to remedy this situation, the `git submodule sync` command is required: + +[source,console] +---- +# copy the new URL to your local config +$ git submodule sync --recursive +# update the submodule from the new URL +$ git submodule update --init --recursive +---- ===== Working on a Submodule @@ -379,30 +459,32 @@ Otherwise you would probably instead be using a simpler dependency management sy So now let's go through an example of making changes to the submodule at the same time as the main project and committing and publishing those changes at the same time. -So far, when we've run the `git submodule update` command to fetch changes from the submodule repositories, Git would get the changes and update the files in the subdirectory but will leave the sub-repository in what's called a ``detached HEAD'' state. -This means that there is no local working branch (like ``master'', for example) tracking changes. +So far, when we've run the `git submodule update` command to fetch changes from the submodule repositories, Git would get the changes and update the files in the subdirectory but will leave the sub-repository in what's called a "`detached HEAD`" state. +This means that there is no local working branch (like `master`, for example) tracking changes. With no working branch tracking changes, that means even if you commit changes to the submodule, those changes will quite possibly be lost the next time you run `git submodule update`. You have to do some extra steps if you want changes in a submodule to be tracked. In order to set up your submodule to be easier to go in and hack on, you need to do two things. You need to go into each submodule and check out a branch to work on. -Then you need to tell Git what to do if you have made changes and then `git submodule update --remote` pulls in new work from upstream. +Then you need to tell Git what to do if you have made changes and later `git submodule update --remote` pulls in new work from upstream. The options are that you can merge them into your local work, or you can try to rebase your local work on top of the new changes. First of all, let's go into our submodule directory and check out a branch. [source,console] ---- +$ cd DbConnector/ $ git checkout stable Switched to branch 'stable' ---- -Let's try it with the ``merge'' option. +Let's try updating our submodule with the "`merge`" option. To specify it manually, we can just add the `--merge` option to our `update` call. Here we'll see that there was a change on the server for this submodule and it gets merged in. [source,console] ---- +$ cd .. $ git submodule update --remote --merge remote: Counting objects: 4, done. remote: Compressing objects: 100% (2/2), done. @@ -417,15 +499,15 @@ Fast-forward Submodule path 'DbConnector': merged in '92c7337b30ef9e0893e758dac2459d07362ab5ea' ---- -If we go into the DbConnector directory, we have the new changes already merged into our local `stable` branch. -Now let's see what happens when we make our own local change to the library and someone else pushes another change upstream at the same time. +If we go into the `DbConnector` directory, we have the new changes already merged into our local `stable` branch. +Now let's see what happens when we make our own local change to the library and someone else pushes another change to the upstream at the same time. [source,console] ---- $ cd DbConnector/ $ vim src/db.c -$ git commit -am 'unicode support' -[stable f906e16] unicode support +$ git commit -am 'Unicode support' +[stable f906e16] Unicode support 1 file changed, 1 insertion(+) ---- @@ -433,9 +515,10 @@ Now if we update our submodule we can see what happens when we have made a local [source,console] ---- +$ cd .. $ git submodule update --remote --rebase First, rewinding head to replay your work on top of it... -Applying: unicode support +Applying: Unicode support Submodule path 'DbConnector': rebased into '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94' ---- @@ -449,7 +532,7 @@ Submodule path 'DbConnector': checked out '5d60ef9bbebf5a0c1c1050f242ceeb54ad58d If this happens, don't worry, you can simply go back into the directory and check out your branch again (which will still contain your work) and merge or rebase `origin/stable` (or whatever remote branch you want) manually. -If you haven't committed your changes in your submodule and you run a submodule update that would cause issues, Git will fetch the changes but not overwrite unsaved work in your submodule directory. +If you haven't committed your changes in your submodule and you run a `submodule update` that would cause issues, Git will fetch the changes but not overwrite unsaved work in your submodule directory. [source,console] ---- @@ -492,18 +575,18 @@ Some of these were brought in from upstream by our updates and others were made $ git diff Submodule DbConnector c87d55d..82d2ad3: > Merge from origin/stable - > updated setup script - > unicode support - > remove unnecessary method - > add new option for conn pooling + > Update setup script + > Unicode support + > Remove unnecessary method + > Add new option for conn pooling ---- If we commit in the main project and push it up without pushing the submodule changes up as well, other people who try to check out our changes are going to be in trouble since they will have no way to get the submodule changes that are depended on. Those changes will only exist on our local copy. In order to make sure this doesn't happen, you can ask Git to check that all your submodules have been pushed properly before pushing the main project. -The `git push` command takes the `--recurse-submodules` argument which can be set to either ``check'' or ``on-demand''. -The ``check'' option will make `push` simply fail if any of the committed submodule changes haven't been pushed. +The `git push` command takes the `--recurse-submodules` argument which can be set to either "`check`" or "`on-demand`". +The "`check`" option will make `push` simply fail if any of the committed submodule changes haven't been pushed. [source,console] ---- @@ -525,9 +608,9 @@ to push them to a remote. As you can see, it also gives us some helpful advice on what we might want to do next. The simple option is to go into each submodule and manually push to the remotes to make sure they're externally available and then try this push again. -If you want the check behavior to happen for all pushes, you can make this behavior the default by doing `git config push.recurseSubmodules check`. +If you want the "`check`" behavior to happen for all pushes, you can make this behavior the default by doing `git config push.recurseSubmodules check`. -The other option is to use the ``on-demand'' value, which will try to do this for you. +The other option is to use the "`on-demand`" value, which will try to do this for you. [source,console] ---- @@ -549,7 +632,7 @@ To https://github.com/chaconinc/MainProject 3d6d338..9a377d1 master -> master ---- -As you can see there, Git went into the DbConnector module and pushed it before pushing the main project. +As you can see there, Git went into the `DbConnector` module and pushed it before pushing the main project. If that submodule push fails for some reason, the main project push will also fail. You can make this behavior the default by doing `git config push.recurseSubmodules on-demand`. @@ -580,7 +663,7 @@ Automatic merge failed; fix conflicts and then commit the result. ---- So basically what has happened here is that Git has figured out that the two branches record points in the submodule's history that are divergent and need to be merged. -It explains it as ``merge following commits not found'', which is confusing but we'll explain why that is in a bit. +It explains it as "`merge following commits not found`", which is confusing but we'll explain why that is in a bit. To solve the problem, you need to figure out what state the submodule should be in. Strangely, Git doesn't really give you much information to help out here, not even the SHA-1s of the commits of both sides of the history. @@ -605,7 +688,7 @@ This is what you'll have to merge in and resolve. You can either just try the merge with the SHA-1 directly, or you can create a branch for it and then try to merge that in. We would suggest the latter, even if only to make a nicer merge commit message. -So, we will go into our submodule directory, create a branch based on that second SHA-1 from `git diff` and manually merge. +So, we will go into our submodule directory, create a branch named "`try-merge`" based on that second SHA-1 from `git diff`, and manually merge. [source,console] ---- @@ -615,7 +698,8 @@ $ git rev-parse HEAD eb41d764bccf88be77aced643c13a7fa86714135 $ git branch try-merge c771610 -(DbConnector) $ git merge try-merge + +$ git merge try-merge Auto-merging src/main.c CONFLICT (content): Merge conflict in src/main.c Recorded preimage for 'src/main.c' @@ -648,11 +732,11 @@ $ git commit -m "Merge Tom's Changes" <5> [master 10d2c60] Merge Tom's Changes ---- -<1> First we resolve the conflict -<2> Then we go back to the main project directory -<3> We can check the SHA-1s again -<4> Resolve the conflicted submodule entry -<5> Commit our merge +<1> First we resolve the conflict. +<2> Then we go back to the main project directory. +<3> We can check the SHA-1s again. +<4> Resolve the conflicted submodule entry. +<5> Commit our merge. It can be a bit confusing, but it's really not very hard. @@ -660,7 +744,7 @@ Interestingly, there is another case that Git handles. If a merge commit exists in the submodule directory that contains *both* commits in its history, Git will suggest it to you as a possible solution. It sees that at some point in the submodule project, someone merged branches containing these two commits, so maybe you'll want that one. -This is why the error message from before was ``merge following commits not found'', because it could not do *this*. +This is why the error message from before was "`merge following commits not found`", because it could not do *this*. It's confusing because who would expect it to *try* to do this? If it does find a single acceptable merge commit, you'll see something like this: @@ -695,7 +779,7 @@ Fast-forward $ cd .. $ git add DbConnector -$ git commit -am 'Fast forwarded to a common submodule child' +$ git commit -am 'Fast forward to a common submodule child' ---- This accomplishes the same thing, but at least this way you can verify that it works and you have the code in your submodule directory when you're done. @@ -793,11 +877,16 @@ This way you can simply run `git supdate` when you want to update your submodule Using submodules isn't without hiccups, however. -For instance switching branches with submodules in them can also be tricky. +===== Switching branches + +For instance, switching branches with submodules in them can also be tricky with Git versions older than Git 2.13. If you create a new branch, add a submodule there, and then switch back to a branch without that submodule, you still have the submodule directory as an untracked directory: [source,console] ---- +$ git --version +git version 2.12.2 + $ git checkout -b add-crypto Switched to a new branch 'add-crypto' @@ -805,8 +894,8 @@ $ git submodule add https://github.com/chaconinc/CryptoLibrary Cloning into 'CryptoLibrary'... ... -$ git commit -am 'adding crypto library' -[add-crypto 4445836] adding crypto library +$ git commit -am 'Add crypto library' +[add-crypto 4445836] Add crypto library 2 files changed, 4 insertions(+) create mode 160000 CryptoLibrary @@ -849,6 +938,48 @@ Makefile includes scripts src Again, not really very difficult, but it can be a little confusing. +Newer Git versions (Git >= 2.13) simplify all this by adding the `--recurse-submodules` flag to the `git checkout` command, which takes care of placing the submodules in the right state for the branch we are switching to. + +[source,console] +---- +$ git --version +git version 2.13.3 + +$ git checkout -b add-crypto +Switched to a new branch 'add-crypto' + +$ git submodule add https://github.com/chaconinc/CryptoLibrary +Cloning into 'CryptoLibrary'... +... + +$ git commit -am 'Add crypto library' +[add-crypto 4445836] Add crypto library + 2 files changed, 4 insertions(+) + create mode 160000 CryptoLibrary + +$ git checkout --recurse-submodules master +Switched to branch 'master' +Your branch is up-to-date with 'origin/master'. + +$ git status +On branch master +Your branch is up-to-date with 'origin/master'. + +nothing to commit, working tree clean +---- + +Using the `--recurse-submodules` flag of `git checkout` can also be useful when you work on several branches in the superproject, each having your submodule pointing at different commits. +Indeed, if you switch between branches that record the submodule at different commits, upon executing `git status` the submodule will appear as "`modified`", and indicate "`new commits`". +That is because the submodule state is by default not carried over when switching branches. + +This can be really confusing, so it's a good idea to always `git checkout --recurse-submodules` when your project has submodules. +For older Git versions that do not have the `--recurse-submodules` flag, after the checkout you can use `git submodule update --init --recursive` to put the submodules in the right state. + +Luckily, you can tell Git (>=2.14) to always use the `--recurse-submodules` flag by setting the configuration option `submodule.recurse`: `git config submodule.recurse true`. +As noted above, this will also make Git recurse into submodules for every command that has a `--recurse-submodules` option (except `git clone`). + +===== Switching from subdirectories to submodules + The other main caveat that many people run into involves switching from subdirectories to submodules. If you've been tracking files in your project and you want to move them out into a submodule, you must be careful or Git will get angry at you. Assume that you have files in a subdirectory of your project, and you want to switch it to a submodule. @@ -877,7 +1008,7 @@ Checking connectivity... done. ---- Now suppose you did that in a branch. -If you try to switch back to a branch where those files are still in the actual tree rather than a submodule – you get this error: +If you try to switch back to a branch where those files are still in the actual tree rather than a submodule -- you get this error: [source,console] ---- diff --git a/book/07-git-tools/sections/subtree-merges.asc b/book/07-git-tools/sections/subtree-merges.asc index b6556985d..24bfa3aee 100644 --- a/book/07-git-tools/sections/subtree-merges.asc +++ b/book/07-git-tools/sections/subtree-merges.asc @@ -57,7 +57,7 @@ We just switched back to your `master` branch, and we pull the `rack_branch` bra $ git read-tree --prefix=rack/ -u rack_branch ---- -When we commit, it looks like we have all the Rack files under that subdirectory – as though we copied them in from a tarball. +When we commit, it looks like we have all the Rack files under that subdirectory -- as though we copied them in from a tarball. What gets interesting is that we can fairly easily merge changes from one of the branches to the other. So, if the Rack project updates, we can pull in upstream changes by switching to that branch and pulling: @@ -69,7 +69,7 @@ $ git pull Then, we can merge those changes back into our `master` branch. To pull in the changes and prepopulate the commit message, use the `--squash` option, as well as the recursive merge strategy's `-Xsubtree` option. -(The recursive strategy is the default here, but we include it for clarity.) +The recursive strategy is the default here, but we include it for clarity. [source,console] ---- @@ -80,14 +80,14 @@ Automatic merge went well; stopped before committing as requested ---- All the changes from the Rack project are merged in and ready to be committed locally. -You can also do the opposite – make changes in the `rack` subdirectory of your master branch and then merge them into your `rack_branch` branch later to submit them to the maintainers or push them upstream. +You can also do the opposite -- make changes in the `rack` subdirectory of your `master` branch and then merge them into your `rack_branch` branch later to submit them to the maintainers or push them upstream. This gives us a way to have a workflow somewhat similar to the submodule workflow without using submodules (which we will cover in <>). We can keep branches with other related projects in our repository and subtree merge them into our project occasionally. It is nice in some ways, for example all the code is committed to a single place. However, it has other drawbacks in that it's a bit more complex and easier to make mistakes in reintegrating changes or accidentally pushing a branch into an unrelated repository. -Another slightly weird thing is that to get a diff between what you have in your `rack` subdirectory and the code in your `rack_branch` branch – to see if you need to merge them – you can't use the normal `diff` command. +Another slightly weird thing is that to get a diff between what you have in your `rack` subdirectory and the code in your `rack_branch` branch -- to see if you need to merge them -- you can't use the normal `diff` command. Instead, you must run `git diff-tree` with the branch you want to compare to: [source,console] @@ -95,7 +95,7 @@ Instead, you must run `git diff-tree` with the branch you want to compare to: $ git diff-tree -p rack_branch ---- -Or, to compare what is in your `rack` subdirectory with what the `master` branch on the server was the last time you fetched, you can run +Or, to compare what is in your `rack` subdirectory with what the `master` branch on the server was the last time you fetched, you can run: [source,console] ---- diff --git a/book/08-customizing-git/sections/attributes.asc b/book/08-customizing-git/sections/attributes.asc index 6ade30fd9..cbcad3631 100644 --- a/book/08-customizing-git/sections/attributes.asc +++ b/book/08-customizing-git/sections/attributes.asc @@ -37,7 +37,6 @@ You can also use the Git attributes functionality to effectively diff binary fil You do this by telling Git how to convert your binary data to a text format that can be compared via the normal diff. First, you'll use this technique to solve one of the most annoying problems known to humanity: version-controlling Microsoft Word documents. -Everyone knows that Word is the most horrific editor around, but oddly, everyone still uses it. If you want to version-control Word documents, you can stick them in a Git repository and commit every once in a while; but what good does that do? If you run `git diff` normally, you only see something like this: @@ -58,12 +57,12 @@ Put the following line in your `.gitattributes` file: *.docx diff=word ---- -This tells Git that any file that matches this pattern (`.docx`) should use the ``word'' filter when you try to view a diff that contains changes. -What is the ``word'' filter? +This tells Git that any file that matches this pattern (`.docx`) should use the "`word`" filter when you try to view a diff that contains changes. +What is the "`word`" filter? You have to set it up. Here you'll configure Git to use the `docx2txt` program to convert Word documents into readable text files, which it will then diff properly. -First, you'll need to install `docx2txt`; you can download it from https://sourceforge.net/projects/docx2txt[]. +First, you'll need to install `docx2txt`; you can download it from https://sourceforge.net/projects/docx2txt[^]. Follow the instructions in the `INSTALL` file to put it somewhere your shell can find it. Next, you'll write a wrapper script to convert output to the format Git expects. Create a file that's somewhere in your path called `docx2txt`, and add these contents: @@ -82,7 +81,7 @@ Finally, you can configure Git to use this script: $ git config diff.word.textconv docx2txt ---- -Now Git knows that if it tries to do a diff between two snapshots, and any of the files end in `.docx`, it should run those files through the ``word'' filter, which is defined as the `docx2txt` program. +Now Git knows that if it tries to do a diff between two snapshots, and any of the files end in `.docx`, it should run those files through the "`word`" filter, which is defined as the `docx2txt` program. This effectively makes nice text-based versions of your Word files before attempting to diff them. Here's an example: Chapter 1 of this book was converted to Word format and committed in a Git repository. @@ -106,7 +105,7 @@ index 0b013ca..ba25db5 100644 Many people's version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they're clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you're in and accidentally write to the wrong file or copy over files you don't mean to. ---- -Git successfully and succinctly tells us that we added the string ``Testing: 1, 2, 3.'', which is correct. +Git successfully and succinctly tells us that we added the string "`Testing: 1, 2, 3.`", which is correct. It's not perfect – formatting changes wouldn't show up here – but it certainly works. Another interesting problem you can solve this way involves diffing image files. @@ -192,27 +191,27 @@ However, that result is of limited use. If you've used keyword substitution in CVS or Subversion, you can include a datestamp – the SHA-1 isn't all that helpful, because it's fairly random and you can't tell if one SHA-1 is older or newer than another just by looking at them. It turns out that you can write your own filters for doing substitutions in files on commit/checkout. -These are called ``clean'' and ``smudge'' filters. -In the `.gitattributes` file, you can set a filter for particular paths and then set up scripts that will process files just before they're checked out (``smudge'', see <>) and just before they're staged (``clean'', see <>). +These are called "`clean`" and "`smudge`" filters. +In the `.gitattributes` file, you can set a filter for particular paths and then set up scripts that will process files just before they're checked out ("`smudge`", see <>) and just before they're staged ("`clean`", see <>). These filters can be set to do all sorts of fun things. [[filters_a]] -.The ``smudge'' filter is run on checkout. -image::images/smudge.png[The ``smudge'' filter is run on checkout.] +.The "`smudge`" filter is run on checkout +image::images/smudge.png[The “smudge” filter is run on checkout] [[filters_b]] -.The ``clean'' filter is run when files are staged. -image::images/clean.png[The ``clean'' filter is run when files are staged.] +.The "`clean`" filter is run when files are staged +image::images/clean.png[The “clean” filter is run when files are staged] The original commit message for this feature gives a simple example of running all your C source code through the `indent` program before committing. -You can set it up by setting the filter attribute in your `.gitattributes` file to filter `*.c` files with the ``indent'' filter: +You can set it up by setting the filter attribute in your `.gitattributes` file to filter `\*.c` files with the "`indent`" filter: [source,ini] ---- *.c filter=indent ---- -Then, tell Git what the ``indent'' filter does on smudge and clean: +Then, tell Git what the "`indent`" filter does on smudge and clean: [source,console] ---- @@ -265,7 +264,7 @@ If you commit those changes and check out the file again, you see the keyword pr [source,console] ---- $ git add date_test.txt .gitattributes -$ git commit -m "Testing date expansion in Git" +$ git commit -m "Test date expansion in Git" $ rm date_test.txt $ git checkout date_test.txt $ cat date_test.txt @@ -298,8 +297,7 @@ Now, when you run `git archive` to create a tarball of your project, that direct ===== `export-subst` -When exporting files for deployment you can apply `git log`'s formatting and keyword-expansion processing to selected portions of files marked with the -`export-subst` attribute. +When exporting files for deployment you can apply ``git log```'s formatting and keyword-expansion processing to selected portions of files marked with the ``export-subst`` attribute. For instance, if you want to include a file named `LAST_COMMIT` in your project, and have metadata about the last commit automatically injected into it when `git archive` runs, you can for example set up your `.gitattributes` and `LAST_COMMIT` files like this: diff --git a/book/08-customizing-git/sections/config.asc b/book/08-customizing-git/sections/config.asc index 426b6dda0..16739692f 100644 --- a/book/08-customizing-git/sections/config.asc +++ b/book/08-customizing-git/sections/config.asc @@ -14,7 +14,7 @@ $ git config --global user.email johndoe@example.com Now you'll learn a few of the more interesting options that you can set in this manner to customize your Git usage. First, a quick review: Git uses a series of configuration files to determine non-default behavior that you may want. -The first place Git looks for these values is in the system-wide `/etc/gitconfig` file, which contains settings that are applied to every user on the system and all of their repositories. +The first place Git looks for these values is in the system-wide `[path]/etc/gitconfig` file, which contains settings that are applied to every user on the system and all of their repositories. If you pass the option `--system` to `git config`, it reads and writes from this file specifically. The next place Git looks is the `~/.gitconfig` (or `~/.config/git/config`) file, which is specific to each user. @@ -22,9 +22,9 @@ You can make Git read and write to this file by passing the `--global` option. Finally, Git looks for configuration values in the configuration file in the Git directory (`.git/config`) of whatever repository you're currently using. These values are specific to that single repository, and represent passing the `--local` option to `git config`. -(If you don't specify which level you want to work with, this is the default.) +If you don't specify which level you want to work with, this is the default. -Each of these ``levels'' (system, global, local) overwrites values in the previous level, so values in `.git/config` trump those in `/etc/gitconfig`, for instance. +Each of these "`levels`" (system, global, local) overwrites values in the previous level, so values in `.git/config` trump those in `[path]/etc/gitconfig`, for instance. [NOTE] ==== @@ -37,7 +37,7 @@ It's generally easier to run the `git config` command, though. The configuration options recognized by Git fall into two categories: client-side and server-side. The majority of the options are client-side -- configuring your personal working preferences. Many, _many_ configuration options are supported, but a large fraction of them are useful only in certain edge cases; we'll cover just the most common and useful options here. -If you want to see a list of all the options your version of Git recognizes, you can run +If you want to see a list of all the options your version of Git recognizes, you can run: [source,console] ---- @@ -45,7 +45,12 @@ $ man git-config ---- This command lists all the available options in quite a bit of detail. -You can also find this reference material at https://git-scm.com/docs/git-config[]. +You can also find this reference material at https://git-scm.com/docs/git-config[^]. + +[NOTE] +==== +For advanced use cases you may want to look up "Conditional includes" in the documentation mentioned above. +==== ===== `core.editor` @@ -124,7 +129,7 @@ You can set it to `more` or to your favorite pager (by default, it's `less`), or $ git config --global core.pager '' ---- -If you run that, Git will page the entire output of all commands, no matter how long they are. +If you run that, Git will print the entire output of all commands, no matter how long they are. ===== `user.signingkey` @@ -175,7 +180,7 @@ If you mistype a command, it shows you something like this: $ git chekcout master git: 'chekcout' is not a git command. See 'git --help'. -Did you mean this? +The most similar command is checkout ---- @@ -190,7 +195,8 @@ Continuing under the assumption that you meant 'checkout' in 0.1 seconds automatically... ---- -Note that ``0.1 seconds'' business. `help.autocorrect` is actually an integer which represents tenths of a second. +Note that "`0.1 seconds`" business. +`help.autocorrect` is actually an integer which represents tenths of a second. So if you set it to 50, Git will give you 5 seconds to change your mind before executing the autocorrected command. ==== Colors in Git @@ -226,7 +232,7 @@ Each of these can be set to `true`, `false`, or `always`: color.status In addition, each of these has subsettings you can use to set specific colors for parts of the output, if you want to override each color. -For example, to set the meta information in your diff output to blue foreground, black background, and bold text, you can run +For example, to set the meta information in your diff output to blue foreground, black background, and bold text, you can run: [source,console] ---- @@ -247,7 +253,7 @@ We'll demonstrate setting up the Perforce Visual Merge Tool (P4Merge) to do your If you want to try this out, P4Merge works on all major platforms, so you should be able to do so. We'll use path names in the examples that work on macOS and Linux systems; for Windows, you'll have to change `/usr/local/bin` to an executable path in your environment. -To begin, https://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools[download P4Merge from Perforce]. +To begin, https://www.perforce.com/products/helix-core-apps/merge-diff-tool-p4merge[download P4Merge from Perforce^]. Next, you'll set up external wrapper scripts to run your commands. We'll use the macOS path for the executable; in other systems, it will be where your `p4merge` binary is installed. Set up a merge wrapper script named `extMerge` that calls your binary with all the arguments provided: @@ -286,7 +292,7 @@ $ sudo chmod +x /usr/local/bin/extDiff Now you can set up your config file to use your custom merge resolution and diff tools. This takes a number of custom settings: `merge.tool` to tell Git what strategy to use, `mergetool..cmd` to specify how to run the command, `mergetool..trustExitCode` to tell Git if the exit code of that program indicates a successful merge resolution or not, and `diff.external` to tell Git what command to run for diffs. -So, you can either run four config commands +So, you can either run four config commands: [source,console] ---- @@ -296,6 +302,7 @@ $ git config --global mergetool.extMerge.cmd \ $ git config --global mergetool.extMerge.trustExitCode false $ git config --global diff.external extDiff ---- + or you can edit your `~/.gitconfig` file to add these lines: [source,ini] @@ -318,8 +325,8 @@ $ git diff 32d1776b1^ 32d1776b1 Instead of getting the diff output on the command line, Git fires up P4Merge, which looks something like this: -.P4Merge. -image::images/p4merge.png[P4Merge.] +.P4Merge +image::images/p4merge.png[P4Merge] If you try to merge two branches and subsequently have merge conflicts, you can run the command `git mergetool`; it starts P4Merge to let you resolve the conflicts through that GUI tool. @@ -368,7 +375,7 @@ Some of the tools listed above only work in a windowed environment. If run in a terminal-only session, they will fail. ---- -If you're not interested in using KDiff3 for diff but rather want to use it just for merge resolution, and the kdiff3 command is in your path, then you can run +If you're not interested in using KDiff3 for diff but rather want to use it just for merge resolution, and the kdiff3 command is in your path, then you can run: [source,console] ---- @@ -401,7 +408,7 @@ $ git config --global core.autocrlf true ---- If you're on a Linux or macOS system that uses LF line endings, then you don't want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. -You can tell Git to convert CRLF to LF on commit but not the other way around by setting `core.autocrlf` to input: +You can tell Git to convert CRLF to LF on commit but not the other way around by setting `core.autocrlf` to `input`: [source,console] ---- diff --git a/book/08-customizing-git/sections/hooks.asc b/book/08-customizing-git/sections/hooks.asc index fa80387aa..285ba4ffa 100644 --- a/book/08-customizing-git/sections/hooks.asc +++ b/book/08-customizing-git/sections/hooks.asc @@ -15,7 +15,7 @@ When you initialize a new repository with `git init`, Git populates the hooks di All the examples are written as shell scripts, with some Perl thrown in, but any properly named executable scripts will work fine – you can write them in Ruby or Python or whatever language you are familiar with. If you want to use the bundled hook scripts, you'll have to rename them; their file names all end with `.sample`. -To enable a hook script, put a file in the `hooks` subdirectory of your .git directory that is named appropriately (without any extension) and is executable. +To enable a hook script, put a file in the `hooks` subdirectory of your `.git` directory that is named appropriately (without any extension) and is executable. From that point forward, it should be called. We'll cover most of the major hook filenames here. @@ -114,9 +114,9 @@ You can use this hook to do things like make sure none of the updated references ===== `update` The `update` script is very similar to the `pre-receive` script, except that it's run once for each branch the pusher is trying to update. -If the pusher is trying to push to multiple branches, `pre-receive` runs only once, whereas update runs once per branch they're pushing to. +If the pusher is trying to push to multiple branches, `pre-receive` runs only once, whereas `update` runs once per branch they're pushing to. Instead of reading from stdin, this script takes three arguments: the name of the reference (branch), the SHA-1 that reference pointed to before the push, and the SHA-1 the user is trying to push. -If the update script exits non-zero, only that reference is rejected; other references can still be updated. +If the `update` script exits non-zero, only that reference is rejected; other references can still be updated. ===== `post-receive` @@ -124,3 +124,8 @@ The `post-receive` hook runs after the entire process is completed and can be us It takes the same stdin data as the `pre-receive` hook. Examples include emailing a list, notifying a continuous integration server, or updating a ticket-tracking system – you can even parse the commit messages to see if any tickets need to be opened, modified, or closed. This script can't stop the push process, but the client doesn't disconnect until it has completed, so be careful if you try to do anything that may take a long time. + +[TIP] +==== +If you're writing a script/hook that others will need to read, prefer the long versions of command-line flags; six months from now you'll thank us. +==== diff --git a/book/08-customizing-git/sections/policy.asc b/book/08-customizing-git/sections/policy.asc index d83ba2c24..852a0c03a 100644 --- a/book/08-customizing-git/sections/policy.asc +++ b/book/08-customizing-git/sections/policy.asc @@ -18,7 +18,7 @@ The `update` hook runs once per branch being pushed and takes three arguments: * The new revision being pushed You also have access to the user doing the pushing if the push is being run over SSH. -If you've allowed everyone to connect with a single user (like ``git'') via public-key authentication, you may have to give that user a shell wrapper that determines which user is connecting based on the public key, and set an environment variable accordingly. +If you've allowed everyone to connect with a single user (like "`git`") via public-key authentication, you may have to give that user a shell wrapper that determines which user is connecting based on the public key, and set an environment variable accordingly. Here we'll assume the connecting user is in the `$USER` environment variable, so your update script begins by gathering all the information you need: [source,ruby] @@ -41,7 +41,7 @@ Don't judge – it's easier to demonstrate this way. ===== Enforcing a Specific Commit-Message Format Your first challenge is to enforce that each commit message adheres to a particular format. -Just to have a target, assume that each message has to include a string that looks like ``ref: 1234'' because you want each commit to link to a work item in your ticketing system. +Just to have a target, assume that each message has to include a string that looks like "`ref: 1234`" because you want each commit to link to a work item in your ticketing system. You must look at each commit being pushed up, see if that string is in the commit message, and, if the string is absent from any of the commits, exit non-zero so the push is rejected. You can get a list of the SHA-1 values of all the commits that are being pushed by taking the `$newrev` and `$oldrev` values and passing them to a Git plumbing command called `git rev-list`. @@ -72,7 +72,7 @@ parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 author Scott Chacon 1205815931 -0700 committer Scott Chacon 1240030591 -0700 -changed the version number +Change the version number ---- A simple way to get the commit message from a commit when you have the SHA-1 value is to go to the first blank line and take everything after that. @@ -81,7 +81,7 @@ You can do so with the `sed` command on Unix systems: [source,console] ---- $ git cat-file commit ca82a6 | sed '1,/^$/d' -changed the version number +Change the version number ---- You can use that incantation to grab the commit message from each commit that is trying to be pushed and exit if you see anything that doesn't match. @@ -270,7 +270,7 @@ error: failed to push some refs to 'git@gitserver:project.git' You'll see a remote rejected message for each reference that your hook declined, and it tells you that it was declined specifically because of a hook failure. Furthermore, if someone tries to edit a file they don't have access to and push a commit containing it, they will see something similar. -For instance, if a documentation author tries to push a commit modifying something in the `lib` directory, they see +For instance, if a documentation author tries to push a commit modifying something in the `lib` directory, they see: [source,console] ---- @@ -311,7 +311,7 @@ If that script is in place (in `.git/hooks/commit-msg`) and executable, and you [source,console] ---- -$ git commit -am 'test' +$ git commit -am 'Test' [POLICY] Your message is not formatted correctly ---- @@ -320,8 +320,8 @@ However, if your message contains the proper pattern, Git allows you to commit: [source,console] ---- -$ git commit -am 'test [ref: 132]' -[master e05c914] test [ref: 132] +$ git commit -am 'Test [ref: 132]' +[master e05c914] Test [ref: 132] 1 file changed, 1 insertions(+), 0 deletions(-) ---- @@ -360,7 +360,7 @@ check_directory_perms This is roughly the same script as the server-side part, but with two important differences. First, the ACL file is in a different place, because this script runs from your working directory, not from your `.git` directory. -You have to change the path to the ACL file from this +You have to change the path to the ACL file from this: [source,ruby] ---- @@ -376,14 +376,14 @@ access = get_acl_access_data('.git/acl') The other important difference is the way you get a listing of the files that have been changed. Because the server-side method looks at the log of commits, and, at this point, the commit hasn't been recorded yet, you must get your file listing from the staging area instead. -Instead of +Instead of: [source,ruby] ---- files_modified = `git log -1 --name-only --pretty=format:'' #{ref}` ---- -you have to use +you have to use: [source,ruby] ---- diff --git a/book/09-git-and-other-scms/sections/client-bzr.asc b/book/09-git-and-other-scms/sections/client-bzr.asc deleted file mode 100644 index 3487f9ba6..000000000 --- a/book/09-git-and-other-scms/sections/client-bzr.asc +++ /dev/null @@ -1,130 +0,0 @@ -==== Git and Bazaar - -Among the DVCS, another famous one is http://bazaar.canonical.com[Bazaar]. -Bazaar is free and open source, and is part of the https://www.gnu.org[GNU Project]. -It behaves very differently from Git. -Sometimes, to do the same thing as with Git, you have to use a different keyword, and some keywords that are common don't have the same meaning. -In particular, the branch management is very different and may cause confusion, especially when someone comes from Git's universe. -Nevertheless, it is possible to work on a Bazaar repository from a Git one. - -There are many projects that allow you to use Git as a Bazaar client. -Here we'll use Felipe Contreras' project that you may find at https://github.com/felipec/git-remote-bzr[]. -To install it, you just have to download the file git-remote-bzr in a folder contained in your `$PATH`: -[source,console] ----- -$ wget https://raw.github.com/felipec/git-remote-bzr/master/git-remote-bzr -O ~/bin/git-remote-bzr -$ chmod +x ~/bin/git-remote-bzr ----- - -You also need to have Bazaar installed. -That's all! - -===== Create a Git repository from a Bazaar repository - -It is simple to use. -It is enough to clone a Bazaar repository prefixing it by `bzr::`. -Since Git and Bazaar both do full clones to your machine, it's possible to attach a Git clone to your local Bazaar clone, but it isn't recommended. -It's much easier to attach your Git clone directly to the same place your Bazaar clone is attached to ‒ the central repository. - -Let's suppose that you worked with a remote repository which is at address `bzr+ssh://developer@mybazaarserver:myproject`. -Then you must clone it in the following way: -[source,console] ----- -$ git clone bzr::bzr+ssh://developer@mybazaarserver:myproject myProject-Git -$ cd myProject-Git ----- - -At this point, your Git repository is created but it is not compacted for optimal disk use. -That's why you should also clean and compact your Git repository, especially if it is a big one: -[source,console] ----- -$ git gc --aggressive ----- - -===== Bazaar branches - -Bazaar only allows you to clone branches, but a repository may contain several branches, and `git-remote-bzr` can clone both. -For example, to clone a branch: -[source,console] ----- -$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs/trunk emacs-trunk ----- - -And to clone the whole repository: -[source,console] ----- -$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs emacs ----- - -The second command clones all the branches contained in the emacs repository; nevertheless, it is possible to point out some branches: -[source,console] ----- -$ git config remote-bzr.branches 'trunk, xwindow' ----- - -Some remote repositories don't allow you to list their branches, in which case you have to manually specify them, and even though you could specify the configuration in the cloning command, you may find this easier: - -[source,console] ----- -$ git init emacs -$ git remote add origin bzr::bzr://bzr.savannah.gnu.org/emacs -$ git config remote-bzr.branches 'trunk, xwindow' -$ git fetch ----- - -===== Ignore what is ignored with .bzrignore - -Since you are working on a project managed with Bazaar, you shouldn't create a `.gitignore` file because you _may_ accidentally set it under version control and the other people working with Bazaar would be disturbed. -The solution is to create the `.git/info/exclude` file either as a symbolic link or as a regular file. -We'll see later on how to solve this question. - -Bazaar uses the same model as Git to ignore files, but also has two features which don't have an equivalent into Git. -The complete description may be found in http://doc.bazaar.canonical.com/bzr.2.7/en/user-reference/ignore-help.html[the documentation]. -The two features are: - -1. "!!" allows you to ignore certain file patterns even if they're specified using a "!" rule. -2. "RE:" at the beginning of a line allows you to specify a https://docs.python.org/3/library/re.html[Python regular expression] (Git only allows shell globs). - -As a consequence, there are two different situations to consider: - -1. If the `.bzrignore` file does not contain any of these two specific prefixes, then you can simply make a symbolic link to it in the repository: `ln -s .bzrignore .git/info/exclude` -2. Otherwise, you must create the `.git/info/exclude` file and adapt it to ignore exactly the same files in `.bzrignore`. - -Whatever the case is, you will have to remain vigilant against any change of `.bzrignore` to make sure that the `.git/info/exclude` file always reflects `.bzrignore`. -Indeed, if the `.bzrignore` file were to change and contained one or more lines starting with "!!" or "RE:", Git not being able to interpret these lines, you'll have to adapt your `.git/info/exclude` file to ignore the same files as the ones ignored with `.bzrignore`. -Moreover, if the `.git/info/exclude` file was a symbolic link, you'll have to first delete the symbolic link, copy `.bzrignore` to `.git/info/exclude` and then adapt the latter. -However, be careful with its creation because with Git it is impossible to re-include a file if a parent directory of that file is excluded. - -===== Fetch the changes of the remote repository - -To fetch the changes of the remote, you pull changes as usually, using Git commands. -Supposing that your changes are on the `master` branch, you merge or rebase your work on the `origin/master` branch: -[source,console] ----- -$ git pull --rebase origin ----- - -===== Push your work on the remote repository - -Because Bazaar also has the concept of merge commits, there will be no problem if you push a merge commit. -So you can work on a branch, merge the changes into `master` and push your work. -Then, you create your branches, you test and commit your work as usual. -You finally push your work to the Bazaar repository: -[source,console] ----- -$ git push origin master ----- - -===== Caveats - -Git's remote-helpers framework has some limitations that apply. -In particular, these commands don't work: - -* git push origin :branch-to-delete (Bazaar can't accept ref deletions in this way.) -* git push origin old:new (it will push 'old') -* git push --dry-run origin branch (it will push) - -===== Summary - -Since Git's and Bazaar's models are similar, there isn't a lot of resistance when working across the boundary. -As long as you watch out for the limitations, and are always aware that the remote repository isn't natively Git, you'll be fine. diff --git a/book/09-git-and-other-scms/sections/client-hg.asc b/book/09-git-and-other-scms/sections/client-hg.asc index e92c36449..4f7945683 100644 --- a/book/09-git-and-other-scms/sections/client-hg.asc +++ b/book/09-git-and-other-scms/sections/client-hg.asc @@ -8,7 +8,7 @@ Apart from Git, the most popular is Mercurial, and the two are very similar in m The good news, if you prefer Git's client-side behavior but are working with a project whose source code is controlled with Mercurial, is that there's a way to use Git as a client for a Mercurial-hosted repository. Since the way Git talks to server repositories is through remotes, it should come as no surprise that this bridge is implemented as a remote helper. -The project's name is git-remote-hg, and it can be found at https://github.com/felipec/git-remote-hg[]. +The project's name is git-remote-hg, and it can be found at https://github.com/felipec/git-remote-hg[^]. ===== git-remote-hg @@ -31,10 +31,10 @@ If you have Python installed, this is as simple as: $ pip install mercurial ---- -(If you don't have Python installed, visit https://www.python.org/[] and get it first.) +If you don't have Python installed, visit https://www.python.org/[^] and get it first. The last thing you'll need is the Mercurial client. -Go to https://www.mercurial-scm.org/[] and install it if you haven't already. +Go to https://www.mercurial-scm.org/[^] and install it if you haven't already. Now you're ready to rock. All you need is a Mercurial repository you can push to. @@ -47,7 +47,7 @@ $ hg clone http://selenic.com/repo/hello /tmp/hello ===== Getting Started -Now that we have a suitable ``server-side'' repository, we can go through a typical workflow. +Now that we have a suitable "`server-side`" repository, we can go through a typical workflow. As you'll see, these two systems are similar enough that there isn't much friction. As always with Git, first we clone: @@ -58,14 +58,14 @@ $ git clone hg::/tmp/hello /tmp/hello-git $ cd /tmp/hello-git $ git log --oneline --graph --decorate * ac7955c (HEAD, origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master, master) Create a makefile -* 65bb417 Create a standard "hello, world" program +* 65bb417 Create a standard 'hello, world' program ---- You'll notice that working with a Mercurial repository uses the standard `git clone` command. That's because git-remote-hg is working at a fairly low level, using a similar mechanism to how Git's HTTP/S protocol is implemented (remote helpers). Since Git and Mercurial are both designed for every client to have a full copy of the repository history, this command makes a full clone, including all the project's history, and does it fairly quickly. -The log command shows two commits, the latest of which is pointed to by a whole slew of refs. +The `log` command shows two commits, the latest of which is pointed to by a whole slew of refs. It turns out some of these aren't actually there. Let's take a look at what's actually in the `.git` directory: @@ -74,18 +74,18 @@ Let's take a look at what's actually in the `.git` directory: $ tree .git/refs .git/refs ├── heads -│   └── master +│ └── master ├── hg -│   └── origin -│   ├── bookmarks -│   │   └── master -│   └── branches -│   └── default +│ └── origin +│ ├── bookmarks +│ │ └── master +│ └── branches +│ └── default ├── notes -│   └── hg +│ └── hg ├── remotes -│   └── origin -│   └── HEAD +│ └── origin +│ └── HEAD └── tags 9 directories, 5 files @@ -93,7 +93,7 @@ $ tree .git/refs Git-remote-hg is trying to make things more idiomatically Git-esque, but under the hood it's managing the conceptual mapping between two slightly different systems. The `refs/hg` directory is where the actual remote refs are stored. -For example, the `refs/hg/origin/branches/default` is a Git ref file that contains the SHA-1 starting with ``ac7955c'', which is the commit that `master` points to. +For example, the `refs/hg/origin/branches/default` is a Git ref file that contains the SHA-1 starting with "`ac7955c`", which is the commit that `master` points to. So the `refs/hg` directory is kind of like a fake `refs/remotes/origin`, but it has the added distinction between bookmarks and branches. The `notes/hg` file is the starting point for how git-remote-hg maps Git commit hashes to Mercurial changeset IDs. @@ -121,7 +121,7 @@ $ git cat-file -p ac9117f So `refs/notes/hg` points to a tree, which in the Git object database is a list of other objects with names. `git ls-tree` outputs the mode, type, object hash, and filename for items inside a tree. -Once we dig down to one of the tree items, we find that inside it is a blob named ``ac9117f'' (the SHA-1 hash of the commit pointed to by `master`), with contents ``0a04b98'' (which is the ID of the Mercurial changeset at the tip of the `default` branch). +Once we dig down to one of the tree items, we find that inside it is a blob named "`ac9117f`" (the SHA-1 hash of the commit pointed to by `master`), with contents "`0a04b98`" (which is the ID of the Mercurial changeset at the tip of the `default` branch). The good news is that we mostly don't have to worry about all of this. The typical workflow won't be very different from working with a Git remote. @@ -148,7 +148,7 @@ $ git log --oneline --graph --decorate * ba04a2a (HEAD, master) Update makefile * d25d16f Goodbye * ac7955c (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Create a makefile -* 65bb417 Create a standard "hello, world" program +* 65bb417 Create a standard 'hello, world' program ---- Our `master` branch is two commits ahead of `origin/master`, but those two commits exist only on our local machine. @@ -168,10 +168,10 @@ $ git log --oneline --graph --decorate --all | * d25d16f Goodbye |/ * ac7955c Create a makefile -* 65bb417 Create a standard "hello, world" program +* 65bb417 Create a standard 'hello, world' program ---- -Since we used the `--all` flag, we see the ``notes'' refs that are used internally by git-remote-hg, but we can ignore them. +Since we used the `--all` flag, we see the "`notes`" refs that are used internally by git-remote-hg, but we can ignore them. The rest is what we expected; `origin/master` has advanced by one commit, and our history has now diverged. Unlike the other systems we work with in this chapter, Mercurial is capable of handling merges, so we're not going to do anything fancy. @@ -190,7 +190,7 @@ $ git log --oneline --graph --decorate * | d25d16f Goodbye |/ * ac7955c Create a makefile -* 65bb417 Create a standard "hello, world" program +* 65bb417 Create a standard 'hello, world' program ---- Perfect. @@ -225,7 +225,7 @@ o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm | Create a makefile | o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm - Create a standard "hello, world" program + Create a standard 'hello, world' program ---- The changeset numbered _2_ was made by Mercurial, and the changesets numbered _3_ and _4_ were made by git-remote-hg, by pushing commits made with Git. @@ -233,9 +233,9 @@ The changeset numbered _2_ was made by Mercurial, and the changesets numbered _3 ===== Branches and Bookmarks Git has only one kind of branch: a reference that moves when commits are made. -In Mercurial, this kind of a reference is called a ``bookmark,'' and it behaves in much the same way as a Git branch. +In Mercurial, this kind of a reference is called a "`bookmark,`" and it behaves in much the same way as a Git branch. -Mercurial's concept of a ``branch'' is more heavyweight. +Mercurial's concept of a "`branch`" is more heavyweight. The branch that a changeset is made on is recorded _with the changeset_, which means it will always be in the repository history. Here's an example of a commit that was made on the `develop` branch: @@ -250,7 +250,7 @@ date: Thu Aug 14 20:06:38 2014 -0700 summary: More documentation ---- -Note the line that begins with ``branch''. +Note the line that begins with "`branch`". Git can't really replicate this (and doesn't need to; both types of branch can be represented as a Git ref), but git-remote-hg needs to understand the difference, because Mercurial cares. Creating Mercurial bookmarks is as easy as creating Git branches. @@ -292,13 +292,13 @@ o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm | Create a makefile | o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm - Create a standard "hello, world" program + Create a standard 'hello, world' program ---- Note the new `[featureA]` tag on revision 5. These act exactly like Git branches on the Git side, with one exception: you can't delete a bookmark from the Git side (this is a limitation of remote helpers). -You can work on a ``heavyweight'' Mercurial branch also: just put a branch in the `branches` namespace: +You can work on a "`heavyweight`" Mercurial branch also: just put a branch in the `branches` namespace: [source,console] ---- @@ -344,7 +344,7 @@ o changeset: 5:bd5ac26f11f9 [...] ---- -The branch name ``permanent'' was recorded with the changeset marked _7_. +The branch name "`permanent`" was recorded with the changeset marked _7_. From the Git side, working with either of these branch styles is the same: just checkout, commit, fetch, merge, pull, and push as you normally would. One thing you should know is that Mercurial doesn't support rewriting history, only adding to it. @@ -390,7 +390,6 @@ o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm Changesets _8_, _9_, and _10_ have been created and belong to the `permanent` branch, but the old changesets are still there. This can be *very* confusing for your teammates who are using Mercurial, so try to avoid it. - ===== Mercurial Summary Git and Mercurial are similar enough that working across the boundary is fairly painless. diff --git a/book/09-git-and-other-scms/sections/client-p4.asc b/book/09-git-and-other-scms/sections/client-p4.asc index 311aa0777..16708c118 100644 --- a/book/09-git-and-other-scms/sections/client-p4.asc +++ b/book/09-git-and-other-scms/sections/client-p4.asc @@ -8,29 +8,29 @@ As such, it's designed with the constraints of its day; it assumes you're always To be sure, its features and constraints are well-suited to several specific problems, but there are lots of projects using Perforce where Git would actually work better. There are two options if you'd like to mix your use of Perforce and Git. -The first one we'll cover is the ``Git Fusion'' bridge from the makers of Perforce, which lets you expose subtrees of your Perforce depot as read-write Git repositories. +The first one we'll cover is the "`Git Fusion`" bridge from the makers of Perforce, which lets you expose subtrees of your Perforce depot as read-write Git repositories. The second is git-p4, a client-side bridge that lets you use Git as a Perforce client, without requiring any reconfiguration of the Perforce server. [[_p4_git_fusion]] ===== Git Fusion (((Perforce, Git Fusion))) -Perforce provides a product called Git Fusion (available at http://www.perforce.com/git-fusion[]), which synchronizes a Perforce server with Git repositories on the server side. +Perforce provides a product called Git Fusion (available at https://www.perforce.com/manuals/git-fusion/[^]), which synchronizes a Perforce server with Git repositories on the server side. ====== Setting Up For our examples, we'll be using the easiest installation method for Git Fusion, which is downloading a virtual machine that runs the Perforce daemon and Git Fusion. -You can get the virtual machine image from http://www.perforce.com/downloads/Perforce/20-User[], and once it's finished downloading, import it into your favorite virtualization software (we'll use VirtualBox). +You can get the virtual machine image from https://www.perforce.com/downloads[^], and once it's finished downloading, import it into your favorite virtualization software (we'll use VirtualBox). Upon first starting the machine, it asks you to customize the password for three Linux users (`root`, `perforce`, and `git`), and provide an instance name, which can be used to distinguish this installation from others on the same network. When that has all completed, you'll see this: -.The Git Fusion virtual machine boot screen. -image::images/git-fusion-boot.png[The Git Fusion virtual machine boot screen.] +.The Git Fusion virtual machine boot screen +image::images/git-fusion-boot.png[The Git Fusion virtual machine boot screen] You should take note of the IP address that's shown here, we'll be using it later on. Next, we'll create a Perforce user. -Select the ``Login'' option at the bottom and press enter (or SSH to the machine), and log in as `root`. +Select the "`Login`" option at the bottom and press enter (or SSH to the machine), and log in as `root`. Then use these commands to create a user: [source,console] @@ -83,15 +83,15 @@ The file structure looks like this: $ tree . ├── objects -│   ├── repos -│   │   └── [...] -│   └── trees -│   └── [...] +│ ├── repos +│ │ └── [...] +│ └── trees +│ └── [...] │ ├── p4gf_config ├── repos -│   └── Talkhouse -│   └── p4gf_config +│ └── Talkhouse +│ └── p4gf_config └── users └── p4gf_usermap @@ -186,7 +186,7 @@ Note that the email addresses and full names should be unique, unless you want a Perforce Git Fusion is a two-way bridge between Perforce and Git version control. Let's have a look at how it feels to work from the Git side. -We'll assume we've mapped in the ``Jam'' project using a configuration file as shown above, which we can clone like this: +We'll assume we've mapped in the "`Jam`" project using a configuration file as shown above, which we can clone like this: [source,console] ---- @@ -288,8 +288,8 @@ To https://10.0.1.254/Jam Git thinks it worked. Let's take a look at the history of the `README` file from Perforce's point of view, using the revision graph feature of `p4v`: -.Perforce revision graph resulting from Git push. -image::images/git-fusion-perforce-graph.png[Perforce revision graph resulting from Git push.] +.Perforce revision graph resulting from Git push +image::images/git-fusion-perforce-graph.png[Perforce revision graph resulting from Git push] If you've never seen this view before, it may seem confusing, but it shows the same concepts as a graphical viewer for Git history. We're looking at the history of the `README` file, so the directory tree at top left only shows that file as it surfaces in various branches. @@ -297,7 +297,7 @@ At top right, we have a visual graph of how different revisions of the file are The rest of the view is given to the details view for the selected revision (`2` in this case). One thing to notice is that the graph looks exactly like the one in Git's history. -Perforce didn't have a named branch to store the `1` and `2` commits, so it made an ``anonymous'' branch in the `.git-fusion` directory to hold it. +Perforce didn't have a named branch to store the `1` and `2` commits, so it made an "`anonymous`" branch in the `.git-fusion` directory to hold it. This will also happen for named Git branches that don't correspond to a named Perforce branch (and you can later map them to a Perforce branch using the configuration file). Most of this happens behind the scenes, but the end result is that one person on a team can be using Git, another can be using Perforce, and neither of them will know about the other's choice. @@ -323,7 +323,7 @@ Git-p4 isn't as flexible or complete a solution as Git Fusion, but it does allow [NOTE] ====== You'll need the `p4` tool somewhere in your `PATH` to work with git-p4. -As of this writing, it is freely available at http://www.perforce.com/downloads/Perforce/20-User[]. +As of this writing, it is freely available at https://www.perforce.com/downloads/helix-command-line-client-p4[^]. ====== ====== Setting Up @@ -350,7 +350,7 @@ Initialized empty Git repository in /private/tmp/www-shallow/.git/ Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master ---- -This creates what in Git terms is a ``shallow'' clone; only the very latest Perforce revision is imported into Git; remember, Perforce isn't designed to give every revision to every user. +This creates what in Git terms is a "`shallow`" clone; only the very latest Perforce revision is imported into Git; remember, Perforce isn't designed to give every revision to every user. This is enough to use Git as a Perforce client, but for other purposes it's not enough. Once it's finished, we have a fully-functional Git repository: @@ -362,7 +362,7 @@ $ git log --oneline --all --graph --decorate * 70eaf78 (HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head ---- -Note how there's a ``p4'' remote for the Perforce server, but everything else looks like a standard clone. +Note how there's a "`p4`" remote for the Perforce server, but everything else looks like a standard clone. Actually, that's a bit misleading; there isn't actually a remote there. [source,console] @@ -557,7 +557,7 @@ $ git log --oneline --all --graph --decorate * 70eaf78 Initial import of //depot/www/live/ from the state at revision #head ---- -The Git and Perforce history diverge after 775a46f. +The Git and Perforce history diverge after `775a46f`. The Git side has two commits, then a merge commit with the Perforce head, then another commit. We're going to try to submit these on top of a single changeset on the Perforce side. Let's see what would happen if we tried to submit now: @@ -638,7 +638,7 @@ $ cd project; git log --oneline --all --graph --decorate * 2b83451 Project init ---- -Note the ``@all'' specifier in the depot path; that tells git-p4 to clone not just the latest changeset for that subtree, but all changesets that have ever touched those paths. +Note the "`@all`" specifier in the depot path; that tells git-p4 to clone not just the latest changeset for that subtree, but all changesets that have ever touched those paths. This is closer to Git's concept of a clone, but if you're working on a project with a long history, it could take a while. The `--detect-branches` flag tells git-p4 to use Perforce's branch specs to map the branches to Git refs. @@ -653,7 +653,7 @@ $ git config git-p4.branchList main:dev $ git clone --detect-branches //depot/project@all . ---- -Setting the `git-p4.branchList` configuration variable to `main:dev` tells git-p4 that ``main'' and ``dev'' are both branches, and the second one is a child of the first one. +Setting the `git-p4.branchList` configuration variable to `main:dev` tells git-p4 that "`main`" and "`dev`" are both branches, and the second one is a child of the first one. If we now `git checkout -b dev p4/project/dev` and make some commits, git-p4 is smart enough to target the right branch when we do `git p4 submit`. Unfortunately, git-p4 can't mix shallow clones and multiple branches; if you have a huge project and want to work on more than one branch, you'll have to `git p4 clone` once for each branch you want to submit to. diff --git a/book/09-git-and-other-scms/sections/client-svn.asc b/book/09-git-and-other-scms/sections/client-svn.asc index a3e0d87fa..de330a1b2 100644 --- a/book/09-git-and-other-scms/sections/client-svn.asc +++ b/book/09-git-and-other-scms/sections/client-svn.asc @@ -58,7 +58,7 @@ $ svnsync init file:///tmp/test-svn \ ---- This sets up the properties to run the sync. -You can then clone the code by running +You can then clone the code by running: [source,console] ---- @@ -78,7 +78,7 @@ Subversion has to clone one revision at a time and then push it back into anothe Now that you have a Subversion repository to which you have write access, you can go through a typical workflow. You'll start with the `git svn clone` command, which imports an entire Subversion repository into a local Git repository. -Remember that if you're importing from a real hosted Subversion repository, you should replace the `file:///tmp/test-svn` here with the URL of your Subversion repository: +Remember that if you're importing from a real hosted Subversion repository, you should replace the `\file:///tmp/test-svn` here with the URL of your Subversion repository: [source,console] ---- @@ -158,7 +158,7 @@ c3dcbe8488c6240392e8a5d7553bbffcb0f94ef0 refs/remotes/origin/master 6dcb09b5b57875f334f61aebed695e2e4193db5e refs/tags/v1.0.0 ---- -Git fetches the tags directly into `refs/tags`, rather than treating them remote branches. +Git fetches the tags directly into `refs/tags`, rather than treating them as remote branches. ===== Committing Back to Subversion @@ -362,7 +362,7 @@ It's important to note that it doesn't check you out into that branch; if you co Git figures out what branch your dcommits go to by looking for the tip of any of your Subversion branches in your history – you should have only one, and it should be the last one with a `git-svn-id` in your current branch history. If you want to work on more than one branch simultaneously, you can set up local branches to `dcommit` to specific Subversion branches by starting them at the imported Subversion commit for that branch. -If you want an `opera` branch that you can work on separately, you can run +If you want an `opera` branch that you can work on separately, you can run: [source,console] ---- @@ -370,7 +370,7 @@ $ git branch opera remotes/origin/opera ---- Now, if you want to merge your `opera` branch into `trunk` (your `master` branch), you can do so with a normal `git merge`. -But you need to provide a descriptive commit message (via `-m`), or the merge will say ``Merge branch opera'' instead of something useful. +But you need to provide a descriptive commit message (via `-m`), or the merge will say "`Merge branch opera`" instead of something useful. Remember that although you're using `git merge` to do this operation, and the merge likely will be much easier than it would be in Subversion (because Git will automatically detect the appropriate merge base for you), this isn't a normal Git merge commit. You have to push this data back to a Subversion server that can't handle a commit that tracks more than one parent; so, after you push it up, it will look like a single commit that squashed in all the work of another branch under a single commit. diff --git a/book/09-git-and-other-scms/sections/client-tfs.asc b/book/09-git-and-other-scms/sections/client-tfs.asc deleted file mode 100644 index 1685a1b1f..000000000 --- a/book/09-git-and-other-scms/sections/client-tfs.asc +++ /dev/null @@ -1,410 +0,0 @@ -==== Git and TFS - -(((Interoperation with other VCSs, TFS))) -(((TFS)))((("TFVC", see="TFS"))) -Git is becoming popular with Windows developers, and if you're writing code on Windows, there's a good chance you're using Microsoft's Team Foundation Server (TFS). -TFS is a collaboration suite that includes defect and work-item tracking, process support for Scrum and others, code review, and version control. -There's a bit of confusion ahead: *TFS* is the server, which supports controlling source code using both Git and their own custom VCS, which they've dubbed *TFVC* (Team Foundation Version Control). -Git support is a somewhat new feature for TFS (shipping with the 2013 version), so all of the tools that predate that refer to the version-control portion as ``TFS'', even though they're mostly working with TFVC. - -If you find yourself on a team that's using TFVC but you'd rather use Git as your version-control client, there's a project for you. - -===== Which Tool - -(((git-tf)))(((git-tfs))) -In fact, there are two: git-tf and git-tfs. - -Git-tfs (found at https://github.com/git-tfs/git-tfs[]) is a .NET project, and (as of this writing) it only runs on Windows. -To work with Git repositories, it uses the .NET bindings for libgit2, a library-oriented implementation of Git which is highly performant and allows a lot of flexibility with the guts of a Git repository. -Libgit2 is not a complete implementation of Git, so to cover the difference git-tfs will actually call the command-line Git client for some operations, so there are no artificial limits on what it can do with Git repositories. -Its support of TFVC features is very mature, since it uses the Visual Studio assemblies for operations with servers. -This does mean you'll need access to those assemblies, which means you need to install a recent version of Visual Studio (any edition since version 2010, including Express since version 2012), or the Visual Studio SDK. - -Git-tf (whose home is at https://gittf.codeplex.com[]) is a Java project, and as such runs on any computer with a Java runtime environment. -It interfaces with Git repositories through JGit (a JVM implementation of Git), which means it has virtually no limitations in terms of Git functions. -However, its support for TFVC is limited as compared to git-tfs – it does not support branches, for instance. - -So each tool has pros and cons, and there are plenty of situations that favor one over the other. -We'll cover the basic usage of both of them in this book. - -[NOTE] -==== -You'll need access to a TFVC-based repository to follow along with these instructions. -These aren't as plentiful in the wild as Git or Subversion repositories, so you may need to create one of your own. -Codeplex (https://www.codeplex.com[]) or Visual Studio Online (https://visualstudio.microsoft.com[]) are both good choices for this. -==== - - -===== Getting Started: `git-tf` - -The first thing you do, just as with any Git project, is clone. -Here's what that looks like with `git-tf`: - -[source,console] ----- -$ git tf clone https://tfs.codeplex.com:443/tfs/TFS13 $/myproject/Main project_git ----- - -The first argument is the URL of a TFVC collection, the second is of the form `$/project/branch`, and the third is the path to the local Git repository that is to be created (this last one is optional). -Git-tf can only work with one branch at a time; if you want to make checkins on a different TFVC branch, you'll have to make a new clone from that branch. - -This creates a fully functional Git repository: - -[source,console] ----- -$ cd project_git -$ git log --all --oneline --decorate -512e75a (HEAD, tag: TFS_C35190, origin_tfs/tfs, master) Checkin message ----- - -This is called a _shallow_ clone, meaning that only the latest changeset has been downloaded. -TFVC isn't designed for each client to have a full copy of the history, so git-tf defaults to only getting the latest version, which is much faster. - -If you have some time, it's probably worth it to clone the entire project history, using the `--deep` option: - -[source,console] ----- -$ git tf clone https://tfs.codeplex.com:443/tfs/TFS13 $/myproject/Main \ - project_git --deep -Username: domain\user -Password: -Connecting to TFS... -Cloning $/myproject into /tmp/project_git: 100%, done. -Cloned 4 changesets. Cloned last changeset 35190 as d44b17a -$ cd project_git -$ git log --all --oneline --decorate -d44b17a (HEAD, tag: TFS_C35190, origin_tfs/tfs, master) Goodbye -126aa7b (tag: TFS_C35189) -8f77431 (tag: TFS_C35178) FIRST -0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \ - Team Project Creation Wizard ----- - -Notice the tags with names like `TFS_C35189`; this is a feature that helps you know which Git commits are associated with TFVC changesets. -This is a nice way to represent it, since you can see with a simple log command which of your commits is associated with a snapshot that also exists in TFVC. -They aren't necessary (and in fact you can turn them off with `git config git-tf.tag false`) – git-tf keeps the real commit-changeset mappings in the `.git/git-tf` file. - - -===== Getting Started: `git-tfs` - -Git-tfs cloning behaves a bit differently. -Observe: - -[source,powershell] ----- -PS> git tfs clone --with-branches \ - https://username.visualstudio.com/DefaultCollection \ - $/project/Trunk project_git -Initialized empty Git repository in C:/Users/ben/project_git/.git/ -C15 = b75da1aba1ffb359d00e85c52acb261e4586b0c9 -C16 = c403405f4989d73a2c3c119e79021cb2104ce44a -Tfs branches found: -- $/tfvc-test/featureA -The name of the local branch will be : featureA -C17 = d202b53f67bde32171d5078968c644e562f1c439 -C18 = 44cd729d8df868a8be20438fdeeefb961958b674 ----- - -Notice the `--with-branches` flag. -Git-tfs is capable of mapping TFVC branches to Git branches, and this flag tells it to set up a local Git branch for every TFVC branch. -This is highly recommended if you've ever branched or merged in TFS, but it won't work with a server older than TFS 2010 – before that release, ``branches'' were just folders, so git-tfs can't tell them from regular folders. - -Let's take a look at the resulting Git repository: - -[source,powershell] ----- -PS> git log --oneline --graph --decorate --all -* 44cd729 (tfs/featureA, featureA) Goodbye -* d202b53 Branched from $/tfvc-test/Trunk -* c403405 (HEAD, tfs/default, master) Hello -* b75da1a New project -PS> git log -1 -commit c403405f4989d73a2c3c119e79021cb2104ce44a -Author: Ben Straub -Date: Fri Aug 1 03:41:59 2014 +0000 - - Hello - - git-tfs-id: [https://username.visualstudio.com/DefaultCollection]$/myproject/Trunk;C16 ----- - -There are two local branches, `master` and `featureA`, which represent the initial starting point of the clone (`Trunk` in TFVC) and a child branch (`featureA` in TFVC). -You can also see that the `tfs` ``remote'' has a couple of refs too: `default` and `featureA`, which represent TFVC branches. -Git-tfs maps the branch you cloned from to `tfs/default`, and others get their own names. - -Another thing to notice is the `git-tfs-id:` lines in the commit messages. -Instead of tags, git-tfs uses these markers to relate TFVC changesets to Git commits. -This has the implication that your Git commits will have a different SHA-1 hash before and after they have been pushed to TFVC. - -===== Git-tf[s] Workflow - -[NOTE] -==== -Regardless of which tool you're using, you should set a couple of Git configuration values to avoid running into issues. - -[source,console] ----- -$ git config set --local core.ignorecase=true -$ git config set --local core.autocrlf=false ----- -==== - -The obvious next thing you're going to want to do is work on the project. -TFVC and TFS have several features that may add complexity to your workflow: - -. Feature branches that aren't represented in TFVC add a bit of complexity. - This has to do with the *very* different ways that TFVC and Git represent branches. -. Be aware that TFVC allows users to ``checkout'' files from the server, locking them so nobody else can edit them. - This obviously won't stop you from editing them in your local repository, but it could get in the way when it comes time to push your changes up to the TFVC server. -. TFS has the concept of ``gated'' checkins, where a TFS build-test cycle has to complete successfully before the checkin is allowed. - This uses the ``shelve'' function in TFVC, which we don't cover in detail here. - You can fake this in a manual fashion with git-tf, and git-tfs provides the `checkintool` command which is gate-aware. - -In the interest of brevity, what we'll cover here is the happy path, which sidesteps or avoids most of these issues. - -===== Workflow: `git-tf` - - -Let's say you've done some work, made a couple of Git commits on `master`, and you're ready to share your progress on the TFVC server. -Here's our Git repository: - -[source,console] ----- -$ git log --oneline --graph --decorate --all -* 4178a82 (HEAD, master) update code -* 9df2ae3 update readme -* d44b17a (tag: TFS_C35190, origin_tfs/tfs) Goodbye -* 126aa7b (tag: TFS_C35189) -* 8f77431 (tag: TFS_C35178) FIRST -* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \ - Team Project Creation Wizard ----- - -We want to take the snapshot that's in the `4178a82` commit and push it up to the TFVC server. -First things first: let's see if any of our teammates did anything since we last connected: - -[source,console] ----- -$ git tf fetch -Username: domain\user -Password: -Connecting to TFS... -Fetching $/myproject at latest changeset: 100%, done. -Downloaded changeset 35320 as commit 8ef06a8. Updated FETCH_HEAD. -$ git log --oneline --graph --decorate --all -* 8ef06a8 (tag: TFS_C35320, origin_tfs/tfs) just some text -| * 4178a82 (HEAD, master) update code -| * 9df2ae3 update readme -|/ -* d44b17a (tag: TFS_C35190) Goodbye -* 126aa7b (tag: TFS_C35189) -* 8f77431 (tag: TFS_C35178) FIRST -* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \ - Team Project Creation Wizard ----- - -Looks like someone else is working, too, and now we have divergent history. -This is where Git shines, but we have two choices of how to proceed: - -. Making a merge commit feels natural as a Git user (after all, that's what `git pull` does), and git-tf can do this for you with a simple `git tf pull`. - Be aware, however, that TFVC doesn't think this way, and if you push merge commits your history will start to look different on both sides, which can be confusing. - However, if you plan on submitting all of your changes as one changeset, this is probably the easiest choice. -. Rebasing makes our commit history linear, which means we have the option of converting each of our Git commits into a TFVC changeset. - Since this leaves the most options open, we recommend you do it this way; git-tf even makes it easy for you with `git tf pull --rebase`. - -The choice is yours. -For this example, we'll be rebasing: - -[source,console] ----- -$ git rebase FETCH_HEAD -First, rewinding head to replay your work on top of it... -Applying: update readme -Applying: update code -$ git log --oneline --graph --decorate --all -* 5a0e25e (HEAD, master) update code -* 6eb3eb5 update readme -* 8ef06a8 (tag: TFS_C35320, origin_tfs/tfs) just some text -* d44b17a (tag: TFS_C35190) Goodbye -* 126aa7b (tag: TFS_C35189) -* 8f77431 (tag: TFS_C35178) FIRST -* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \ - Team Project Creation Wizard ----- - -Now we're ready to make a checkin to the TFVC server. -Git-tf gives you the choice of making a single changeset that represents all the changes since the last one (`--shallow`, which is the default) and creating a new changeset for each Git commit (`--deep`). -For this example, we'll just create one changeset: - -[source,console] ----- -$ git tf checkin -m 'Updating readme and code' -Username: domain\user -Password: -Connecting to TFS... -Checking in to $/myproject: 100%, done. -Checked commit 5a0e25e in as changeset 35348 -$ git log --oneline --graph --decorate --all -* 5a0e25e (HEAD, tag: TFS_C35348, origin_tfs/tfs, master) update code -* 6eb3eb5 update readme -* 8ef06a8 (tag: TFS_C35320) just some text -* d44b17a (tag: TFS_C35190) Goodbye -* 126aa7b (tag: TFS_C35189) -* 8f77431 (tag: TFS_C35178) FIRST -* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \ - Team Project Creation Wizard ----- - -There's a new `TFS_C35348` tag, indicating that TFVC is storing the exact same snapshot as the `5a0e25e` commit. -It's important to note that not every Git commit needs to have an exact counterpart in TFVC; the `6eb3eb5` commit, for example, doesn't exist anywhere on the server. - -That's the main workflow. -There are a couple of other considerations you'll want to keep in mind: - -* There is no branching. - Git-tf can only create Git repositories from one TFVC branch at a time. -* Collaborate using either TFVC or Git, but not both. - Different git-tf clones of the same TFVC repository may have different commit SHA-1 hashes, which will cause no end of headaches. -* If your team's workflow includes collaborating in Git and syncing periodically with TFVC, only connect to TFVC with one of the Git repositories. - -===== Workflow: `git-tfs` - -Let's walk through the same scenario using git-tfs. -Here are the new commits we've made to the `master` branch in our Git repository: - -[source,powershell] ----- -PS> git log --oneline --graph --all --decorate -* c3bd3ae (HEAD, master) update code -* d85e5a2 update readme -| * 44cd729 (tfs/featureA, featureA) Goodbye -| * d202b53 Branched from $/tfvc-test/Trunk -|/ -* c403405 (tfs/default) Hello -* b75da1a New project ----- - -Now let's see if anyone else has done work while we were hacking away: - -[source,powershell] ----- -PS> git tfs fetch -C19 = aea74a0313de0a391940c999e51c5c15c381d91d -PS> git log --all --oneline --graph --decorate -* aea74a0 (tfs/default) update documentation -| * c3bd3ae (HEAD, master) update code -| * d85e5a2 update readme -|/ -| * 44cd729 (tfs/featureA, featureA) Goodbye -| * d202b53 Branched from $/tfvc-test/Trunk -|/ -* c403405 Hello -* b75da1a New project ----- - -Yes, it turns out our coworker has added a new TFVC changeset, which shows up as the new `aea74a0` commit, and the `tfs/default` remote branch has moved. - -As with git-tf, we have two fundamental options for how to resolve this divergent history: - -. Rebase to preserve a linear history. -. Merge to preserve what actually happened. - -In this case, we're going to do a ``deep'' checkin, where every Git commit becomes a TFVC changeset, so we want to rebase. - -[source,powershell] ----- -PS> git rebase tfs/default -First, rewinding head to replay your work on top of it... -Applying: update readme -Applying: update code -PS> git log --all --oneline --graph --decorate -* 10a75ac (HEAD, master) update code -* 5cec4ab update readme -* aea74a0 (tfs/default) update documentation -| * 44cd729 (tfs/featureA, featureA) Goodbye -| * d202b53 Branched from $/tfvc-test/Trunk -|/ -* c403405 Hello -* b75da1a New project ----- - -Now we're ready to complete our contribution by checking in our code to the TFVC server. -We'll use the `rcheckin` command here to create a TFVC changeset for each Git commit in the path from HEAD to the first `tfs` remote branch found (the `checkin` command would only create one changeset, sort of like squashing Git commits). - -[source,powershell] ----- -PS> git tfs rcheckin -Working with tfs remote: default -Fetching changes from TFS to minimize possibility of late conflict... -Starting checkin of 5cec4ab4 'update readme' - add README.md -C20 = 71a5ddce274c19f8fdc322b4f165d93d89121017 -Done with 5cec4ab4b213c354341f66c80cd650ab98dcf1ed, rebasing tail onto new TFS-commit... -Rebase done successfully. -Starting checkin of b1bf0f99 'update code' - edit .git\tfs\default\workspace\ConsoleApplication1/ConsoleApplication1/Program.cs -C21 = ff04e7c35dfbe6a8f94e782bf5e0031cee8d103b -Done with b1bf0f9977b2d48bad611ed4a03d3738df05ea5d, rebasing tail onto new TFS-commit... -Rebase done successfully. -No more to rcheckin. -PS> git log --all --oneline --graph --decorate -* ff04e7c (HEAD, tfs/default, master) update code -* 71a5ddc update readme -* aea74a0 update documentation -| * 44cd729 (tfs/featureA, featureA) Goodbye -| * d202b53 Branched from $/tfvc-test/Trunk -|/ -* c403405 Hello -* b75da1a New project ----- - -Notice how after every successful checkin to the TFVC server, git-tfs is rebasing the remaining work onto what it just did. -That's because it's adding the `git-tfs-id` field to the bottom of the commit messages, which changes the SHA-1 hashes. -This is exactly as designed, and there's nothing to worry about, but you should be aware that it's happening, especially if you're sharing Git commits with others. - -TFS has many features that integrate with its version control system, such as work items, designated reviewers, gated checkins, and so on. -It can be cumbersome to work with these features using only a command-line tool, but fortunately git-tfs lets you launch a graphical checkin tool very easily: - -[source,powershell] ----- -PS> git tfs checkintool -PS> git tfs ct ----- - -It looks a bit like this: - -.The git-tfs checkin tool. -image::images/git-tfs-ct.png[The git-tfs checkin tool.] - -This will look familiar to TFS users, as it's the same dialog that's launched from within Visual Studio. - -Git-tfs also lets you control TFVC branches from your Git repository. -As an example, let's create one: - -[source,powershell] ----- -PS> git tfs branch $/tfvc-test/featureBee -The name of the local branch will be : featureBee -C26 = 1d54865c397608c004a2cadce7296f5edc22a7e5 -PS> git log --oneline --graph --decorate --all -* 1d54865 (tfs/featureBee) Creation branch $/myproject/featureBee -* ff04e7c (HEAD, tfs/default, master) update code -* 71a5ddc update readme -* aea74a0 update documentation -| * 44cd729 (tfs/featureA, featureA) Goodbye -| * d202b53 Branched from $/tfvc-test/Trunk -|/ -* c403405 Hello -* b75da1a New project ----- - -Creating a branch in TFVC means adding a changeset where that branch now exists, and this is projected as a Git commit. -Note also that git-tfs *created* the `tfs/featureBee` remote branch, but `HEAD` is still pointing to `master`. -If you want to work on the newly-minted branch, you'll want to base your new commits on the `1d54865` commit, perhaps by creating a topic branch from that commit. - -===== Git and TFS Summary - -Git-tf and Git-tfs are both great tools for interfacing with a TFVC server. -They allow you to use the power of Git locally, avoid constantly having to round-trip to the central TFVC server, and make your life as a developer much easier, without forcing your entire team to migrate to Git. -If you're working on Windows (which is likely if your team is using TFS), you'll probably want to use git-tfs, since its feature set is more complete, but if you're working on another platform, you'll be using git-tf, which is more limited. -As with most of the tools in this chapter, you should choose one of these version-control systems to be canonical, and use the other one in a subordinate fashion – either Git or TFVC should be the center of collaboration, but not both. diff --git a/book/09-git-and-other-scms/sections/import-bzr.asc b/book/09-git-and-other-scms/sections/import-bzr.asc deleted file mode 100644 index 7dcbbd67a..000000000 --- a/book/09-git-and-other-scms/sections/import-bzr.asc +++ /dev/null @@ -1,156 +0,0 @@ -==== Bazaar -(((Bazaar)))(((Importing, from Bazaar))) - -Bazaar is a DVCS tool much like Git, and as a result it's pretty straightforward to convert a Bazaar repository into a Git one. -To accomplish this, you'll need to import the `bzr-fastimport` plugin. - -===== Getting the bzr-fastimport plugin - -The procedure for installing the fastimport plugin is different on UNIX-like operating systems and on Windows. -In the first case, the simplest is to install the `bzr-fastimport` package that will install all the required dependencies. - -For example, with Debian and derived, you would do the following: - -[source,console] ----- -$ sudo apt-get install bzr-fastimport ----- - -With RHEL, you would do the following: - -[source,console] ----- -$ sudo yum install bzr-fastimport ----- - -With Fedora, since release 22, the new package manager is dnf: - -[source,console] ----- -$ sudo dnf install bzr-fastimport ----- - -If the package is not available, you may install it as a plugin: - -[source,console] ----- -$ mkdir --parents ~/.bazaar/plugins # creates the necessary folders for the plugins -$ cd ~/.bazaar/plugins -$ bzr branch lp:bzr-fastimport fastimport # imports the fastimport plugin -$ cd fastimport -$ sudo python setup.py install --record=files.txt # installs the plugin ----- - -For this plugin to work, you'll also need the `fastimport` Python module. -You can check whether it is present or not and install it with the following commands: - -[source,console] ----- -$ python -c "import fastimport" -Traceback (most recent call last): - File "", line 1, in -ImportError: No module named fastimport -$ pip install fastimport ----- -If it is not available, you can download it at address https://pypi.python.org/pypi/fastimport/. - -In the second case (on Windows), `bzr-fastimport` is automatically installed with the standalone version and the default installation (let all the checkboxes checked). -So in this case you have nothing to do. - -At this point, the way to import a Bazaar repository differs according to that you have a single branch or you are working with a repository that has several branches. - -===== Project with a single branch - -Now `cd` in the directory that contains your Bazaar repository and initialize the Git repository: - -[source,console] ----- -$ cd /path/to/the/bzr/repository -$ git init ----- - -Now, you can simply export your Bazaar repository and convert it into a Git repository using the following command: - -[source,console] ----- -$ bzr fast-export --plain . | git fast-import ----- - -Depending on the size of the project, your Git repository is built in a lapse from a few seconds to a few minutes. - -===== Case of a project with a main branch and a working branch - -You can also import a Bazaar repository that contains branches. -Let us suppose that you have two branches: one represents the main branch (myProject.trunk), the other one is the working branch (myProject.work). - -[source,console] ----- -$ ls -myProject.trunk myProject.work ----- - -Create the Git repository and `cd` into it: - -[source,console] ----- -$ git init git-repo -$ cd git-repo ----- - -Pull the master branch into git: - -[source,console] ----- -$ bzr fast-export --export-marks=../marks.bzr ../myProject.trunk | \ -git fast-import --export-marks=../marks.git ----- - -Pull the working branch into Git: - -[source,console] ----- -$ bzr fast-export --marks=../marks.bzr --git-branch=work ../myProject.work | \ -git fast-import --import-marks=../marks.git --export-marks=../marks.git ----- - -Now `git branch` shows you the `master` branch as well as the `work` branch. -Check the logs to make sure they're complete and get rid of the `marks.bzr` and `marks.git` files. - -===== Synchronizing the staging area - -Whatever the number of branches you had and the import method you used, your staging area is not synchronized with `HEAD`, and with the import of several branches, your working directory is not synchronized either. -This situation is easily solved by the following command: - -[source,console] ----- -$ git reset --hard HEAD ----- - -===== Ignoring the files that were ignored with .bzrignore - -Now let's have a look at the files to ignore. -The first thing to do is to rename `.bzrignore` into `.gitignore`. -If the `.bzrignore` file contains one or several lines starting with "!!" or "RE:", you'll have to modify it and perhaps create several `.gitignore` files in order to ignore exactly the same files that Bazaar was ignoring. - -Finally, you will have to create a commit that contains this modification for the migration: - -[source,console] ----- -$ git mv .bzrignore .gitignore -$ # modify .gitignore if needed -$ git commit -am 'Migration from Bazaar to Git' ----- - -===== Sending your repository to the server - -Here we are! -Now you can push the repository onto its new home server: - -[source,console] ----- -$ git remote add origin git@my-git-server:mygitrepository.git -$ git push origin --all -$ git push origin --tags ----- - -Your Git repository is ready to use. diff --git a/book/09-git-and-other-scms/sections/import-custom.asc b/book/09-git-and-other-scms/sections/import-custom.asc index 14bc9c00b..726f3d8f4 100644 --- a/book/09-git-and-other-scms/sections/import-custom.asc +++ b/book/09-git-and-other-scms/sections/import-custom.asc @@ -55,7 +55,7 @@ end ---- You run `print_export` inside each directory, which takes the manifest and mark of the previous snapshot and returns the manifest and mark of this one; that way, you can link them properly. -``Mark'' is the `fast-import` term for an identifier you give to a commit; as you create commits, you give each one a mark that you can use to link to it from other commits. +"`Mark`" is the `fast-import` term for an identifier you give to a commit; as you create commits, you give each one a mark that you can use to link to it from other commits. So, the first thing to do in your `print_export` method is generate a mark from the directory name: [source,ruby] @@ -155,7 +155,7 @@ Dir.glob("**/*").each do |file| end ---- -Note: Because many systems think of their revisions as changes from one commit to another, fast-import can also take commands with each commit to specify which files have been added, removed, or modified and what the new contents are. +Note: Because many systems think of their revisions as changes from one commit to another, fast-import can also take commands with each commit to specify which files have been added, removed, or modified and what the new contents are. You could calculate the differences between snapshots and provide only this data, but doing so is more complex – you may as well give Git all the data and let it figure it out. If this is better suited to your data, check the `fast-import` man page for details about how to provide your data in this manner. @@ -204,7 +204,6 @@ $stdout.binmode That's it. Here's the script in its entirety: - [source,ruby] ---- #!/usr/bin/env ruby diff --git a/book/09-git-and-other-scms/sections/import-hg.asc b/book/09-git-and-other-scms/sections/import-hg.asc index 132fa8c0f..b6d1e194a 100644 --- a/book/09-git-and-other-scms/sections/import-hg.asc +++ b/book/09-git-and-other-scms/sections/import-hg.asc @@ -39,7 +39,7 @@ Joe Smith In this example, the same person (Bob) has created changesets under four different names, one of which actually looks correct, and one of which would be completely invalid for a Git commit. Hg-fast-export lets us fix this by turning each line into a rule: `""=""`, mapping an `` to an ``. -Inside the `` and `` strings, all escape sequences understood by the python `string_escape` encoding are supported. +Inside the `` and `` strings, all escape sequences understood by the Python `string_escape` encoding are supported. If the author mapping file does not contain a matching ``, that author will be sent on to Git unmodified. If all the usernames look fine, we won't need this file at all. In this example, we want our file to look like this: diff --git a/book/09-git-and-other-scms/sections/import-svn.asc b/book/09-git-and-other-scms/sections/import-svn.asc index 323447c8f..5ed4e8f5c 100644 --- a/book/09-git-and-other-scms/sections/import-svn.asc +++ b/book/09-git-and-other-scms/sections/import-svn.asc @@ -27,11 +27,26 @@ $ svn log --xml --quiet | grep author | sort -u | \ ---- That generates the log output in XML format, then keeps only the lines with author information, discards duplicates, strips out the XML tags. -(Obviously this only works on a machine with `grep`, `sort`, and `perl` installed.) +Obviously this only works on a machine with `grep`, `sort`, and `perl` installed. Then, redirect that output into your `users.txt` file so you can add the equivalent Git user data next to each entry. +[NOTE] +==== +If you're trying this on a Windows machine, this is the point where you'll run into trouble. +Microsoft have provided some good advice and samples at https://learn.microsoft.com/en-us/azure/devops/repos/git/perform-migration-from-svn-to-git[^]. +==== + You can provide this file to `git svn` to help it map the author data more accurately. -You can also tell `git svn` not to include the metadata that Subversion normally imports, by passing `--no-metadata` to the `clone` or `init` command (though if you want to keep the synchronisation-metadata, feel free to omit this parameter). +You can also tell `git svn` not to include the metadata that Subversion normally imports, by passing `--no-metadata` to the `clone` or `init` command. +The metadata includes a `git-svn-id` inside each commit message that Git will generate during import. +This can bloat your Git log and might make it a bit unclear. + +[NOTE] +==== +You need to keep the metadata when you want to mirror commits made in the Git repository back into the original SVN repository. +If you don't want the synchronization in your commit log, feel free to omit the `--no-metadata` parameter. +==== + This makes your `import` command look like this: [source,console] @@ -42,7 +57,7 @@ $ cd my_project ---- Now you should have a nicer Subversion import in your `my_project` directory. -Instead of commits that look like this +Instead of commits that look like this: [source] ---- @@ -90,8 +105,8 @@ $ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git ---- It may happen that you'll see some extra branches which are suffixed by `@xxx` (where xxx is a number), while in Subversion you only see one branch. -This is actually a Subversion feature called ``peg-revisions'', which is something that Git simply has no syntactical counterpart for. -Hence, `git svn` simply adds the svn version number to the branch name just in the same way as you would have written it in svn to address the peg-revision of that branch. +This is actually a Subversion feature called "`peg-revisions`", which is something that Git simply has no syntactical counterpart for. +Hence, `git svn` simply adds the SVN version number to the branch name just in the same way as you would have written it in SVN to address the peg-revision of that branch. If you do not care anymore about the peg-revisions, simply remove them: [source,console] diff --git a/book/09-git-and-other-scms/sections/import-tfs.asc b/book/09-git-and-other-scms/sections/import-tfs.asc deleted file mode 100644 index 68a7f4cf9..000000000 --- a/book/09-git-and-other-scms/sections/import-tfs.asc +++ /dev/null @@ -1,60 +0,0 @@ -[[_git_tfs]] -==== TFS - -(((TFS)))(((Importing, from TFS))) -If your team is converting their source control from TFVC to Git, you'll want the highest-fidelity conversion you can get. -This means that, while we covered both git-tfs and git-tf for the interop section, we'll only be covering git-tfs for this part, because git-tfs supports branches, and this is prohibitively difficult using git-tf. - -[NOTE] -==== -This is a one-way conversion. -The resulting Git repository won't be able to connect with the original TFVC project. -==== - -The first thing to do is map usernames. -TFVC is fairly liberal with what goes into the author field for changesets, but Git wants a human-readable name and email address. -You can get this information from the `tf` command-line client, like so: - -[source,powershell] ----- -PS> tf history $/myproject -recursive > AUTHORS_TMP ----- - -This grabs all of the changesets in the history of the project and put it in the AUTHORS_TMP file that we will process to extract the data of the 'User' column (the 2nd one). -Open the file and find at which characters start and end the column and replace, in the following command-line, the parameters `11-20` of the `cut` command with the ones found: - -[source,powershell] ----- -PS> cat AUTHORS_TMP | cut -b 11-20 | tail -n+3 | sort | uniq > AUTHORS ----- - -The `cut` command keeps only the characters between 11 and 20 from each line. -The `tail` command skips the first two lines, which are field headers and ASCII-art underlines. -The result of all of this is piped to `sort` and `uniq` to eliminate duplicates, and saved to a file named `AUTHORS`. -The next step is manual; in order for git-tfs to make effective use of this file, each line must be in this format: - -[source,text] ----- -DOMAIN\username = User Name ----- - -The portion on the left is the ``User'' field from TFVC, and the portion on the right side of the equals sign is the user name that will be used for Git commits. - -Once you have this file, the next thing to do is make a full clone of the TFVC project you're interested in: - -[source,powershell] ----- -PS> git tfs clone --with-branches --authors=AUTHORS https://username.visualstudio.com/DefaultCollection $/project/Trunk project_git ----- - -Next you'll want to clean the `git-tfs-id` sections from the bottom of the commit messages. -The following command will do that: - -[source,powershell] ----- -PS> git filter-branch -f --msg-filter 'sed "s/^git-tfs-id:.*$//g"' '--' --all ----- - -That uses the `sed` command from the Git-bash environment to replace any line starting with ``git-tfs-id:'' with emptiness, which Git will then ignore. - -Once that's all done, you're ready to add a new remote, push all your branches up, and have your team start working from Git. diff --git a/book/10-git-internals/sections/environment.asc b/book/10-git-internals/sections/environment.asc index f35535bde..9b01781cd 100644 --- a/book/10-git-internals/sections/environment.asc +++ b/book/10-git-internals/sections/environment.asc @@ -4,22 +4,21 @@ Git always runs inside a `bash` shell, and uses a number of shell environment va Occasionally, it comes in handy to know what these are, and how they can be used to make Git behave the way you want it to. This isn't an exhaustive list of all the environment variables Git pays attention to, but we'll cover the most useful. - ==== Global Behavior Some of Git's general behavior as a computer program depends on environment variables. *`GIT_EXEC_PATH`* determines where Git looks for its sub-programs (like `git-commit`, `git-diff`, and others). - You can check the current setting by running `git --exec-path`. +You can check the current setting by running `git --exec-path`. *`HOME`* isn't usually considered customizable (too many other things depend on it), but it's where Git looks for the global configuration file. - If you want a truly portable Git installation, complete with global configuration, you can override `HOME` in the portable Git's shell profile. +If you want a truly portable Git installation, complete with global configuration, you can override `HOME` in the portable Git's shell profile. *`PREFIX`* is similar, but for the system-wide configuration. - Git looks for this file at `$PREFIX/etc/gitconfig`. +Git looks for this file at `$PREFIX/etc/gitconfig`. *`GIT_CONFIG_NOSYSTEM`*, if set, disables the use of the system-wide configuration file. - This is useful if your system config is interfering with your commands, but you don't have access to change or remove it. +This is useful if your system config is interfering with your commands, but you don't have access to change or remove it. *`GIT_PAGER`* controls the program used to display multi-page output on the command line. If this is unset, `PAGER` will be used as a fallback. @@ -27,7 +26,6 @@ If this is unset, `PAGER` will be used as a fallback. *`GIT_EDITOR`* is the editor Git will launch when the user needs to edit some text (a commit message, for example). If unset, `EDITOR` will be used. - ==== Repository Locations Git uses several environment variables to determine how it interfaces with the current repository. @@ -48,41 +46,38 @@ If `--git-dir` or `GIT_DIR` is specified but none of `--work-tree`, `GIT_WORK_TR *`GIT_ALTERNATE_OBJECT_DIRECTORIES`* is a colon-separated list (formatted like `/dir/one:/dir/two:…`) which tells Git where to check for objects if they aren't in `GIT_OBJECT_DIRECTORY`. If you happen to have a lot of projects with large files that have the exact same contents, this can be used to avoid storing too many copies of them. - ==== Pathspecs -A ``pathspec'' refers to how you specify paths to things in Git, including the use of wildcards. +A "`pathspec`" refers to how you specify paths to things in Git, including the use of wildcards. These are used in the `.gitignore` file, but also on the command-line (`git add *.c`). *`GIT_GLOB_PATHSPECS`* and *`GIT_NOGLOB_PATHSPECS`* control the default behavior of wildcards in pathspecs. -If `GIT_GLOB_PATHSPECS` is set to 1, wildcard characters act as wildcards (which is the default); if `GIT_NOGLOB_PATHSPECS` is set to 1, wildcard characters only match themselves, meaning something like `*.c` would only match a file _named_ ``*.c'', rather than any file whose name ends with `.c`. -You can override this in individual cases by starting the pathspec with `:(glob)` or `:(literal)`, as in `:(glob)*.c`. +If `GIT_GLOB_PATHSPECS` is set to 1, wildcard characters act as wildcards (which is the default); if `GIT_NOGLOB_PATHSPECS` is set to 1, wildcard characters only match themselves, meaning something like `\*.c` would only match a file _named_ "`\*.c`", rather than any file whose name ends with `.c`. +You can override this in individual cases by starting the pathspec with `:(glob)` or `:(literal)`, as in `:(glob)\*.c`. *`GIT_LITERAL_PATHSPECS`* disables both of the above behaviors; no wildcard characters will work, and the override prefixes are disabled as well. *`GIT_ICASE_PATHSPECS`* sets all pathspecs to work in a case-insensitive manner. - ==== Committing The final creation of a Git commit object is usually done by `git-commit-tree`, which uses these environment variables as its primary source of information, falling back to configuration values only if these aren't present. -*`GIT_AUTHOR_NAME`* is the human-readable name in the ``author'' field. +*`GIT_AUTHOR_NAME`* is the human-readable name in the "`author`" field. -*`GIT_AUTHOR_EMAIL`* is the email for the ``author'' field. +*`GIT_AUTHOR_EMAIL`* is the email for the "`author`" field. -*`GIT_AUTHOR_DATE`* is the timestamp used for the ``author'' field. +*`GIT_AUTHOR_DATE`* is the timestamp used for the "`author`" field. -*`GIT_COMMITTER_NAME`* sets the human name for the ``committer'' field. +*`GIT_COMMITTER_NAME`* sets the human name for the "`committer`" field. -*`GIT_COMMITTER_EMAIL`* is the email address for the ``committer'' field. +*`GIT_COMMITTER_EMAIL`* is the email address for the "`committer`" field. -*`GIT_COMMITTER_DATE`* is used for the timestamp in the ``committer'' field. +*`GIT_COMMITTER_DATE`* is used for the timestamp in the "`committer`" field. *`EMAIL`* is the fallback email address in case the `user.email` configuration value isn't set. If _this_ isn't set, Git falls back to the system user and host names. - ==== Networking Git uses the `curl` library to do network operations over HTTP, so *`GIT_CURL_VERBOSE`* tells Git to emit all the messages generated by that library. @@ -91,14 +86,12 @@ This is similar to doing `curl -v` on the command line. *`GIT_SSL_NO_VERIFY`* tells Git not to verify SSL certificates. This can sometimes be necessary if you're using a self-signed certificate to serve Git repositories over HTTPS, or you're in the middle of setting up a Git server but haven't installed a full certificate yet. - If the data rate of an HTTP operation is lower than *`GIT_HTTP_LOW_SPEED_LIMIT`* bytes per second for longer than *`GIT_HTTP_LOW_SPEED_TIME`* seconds, Git will abort that operation. These values override the `http.lowSpeedLimit` and `http.lowSpeedTime` configuration values. *`GIT_HTTP_USER_AGENT`* sets the user-agent string used by Git when communicating over HTTP. The default is a value like `git/2.0.0`. - ==== Diffing and Merging *`GIT_DIFF_OPTS`* is a bit of a misnomer. @@ -128,7 +121,7 @@ Want to _really_ know what Git is up to? Git has a fairly complete set of traces embedded, and all you need to do is turn them on. The possible values of these variables are as follows: -* ``true'', ``1'', or ``2'' – the trace category is written to stderr. +* "`true`", "`1`", or "`2`" – the trace category is written to stderr. * An absolute path starting with `/` – the trace output will be written to that file. *`GIT_TRACE`* controls general traces, which don't fit into any specific category. @@ -216,12 +209,14 @@ nothing to commit, working directory clean *`GIT_SSH`*, if specified, is a program that is invoked instead of `ssh` when Git tries to connect to an SSH host. It is invoked like `$GIT_SSH [username@]host [-p ] `. -Note that this isn't the easiest way to customize how `ssh` is invoked; it won't support extra command-line parameters, so you'd have to write a wrapper script and set `GIT_SSH` to point to it. -It's probably easier just to use the `~/.ssh/config` file for that. +Note that this isn't the easiest way to customize how `ssh` is invoked; it won't support extra command-line parameters. +To support extra command-line parameters, you can use *`GIT_SSH_COMMAND`*, write a wrapper script and set `GIT_SSH` to point to it or use the `~/.ssh/config` file. + +*`GIT_SSH_COMMAND`* sets the SSH command used when Git tries to connect to an SSH host. +The command is interpreted by the shell, and extra command-line arguments can be used with `ssh`, such as `GIT_SSH_COMMAND="ssh -i ~/.ssh/my_key" git clone git@example.com:my/repo`. *`GIT_ASKPASS`* is an override for the `core.askpass` configuration value. -This is the program invoked whenever Git needs to ask the user for credentials, which can expect a text prompt as a command-line argument, and should return the answer on `stdout`. -(See <> for more on this subsystem.) +This is the program invoked whenever Git needs to ask the user for credentials, which can expect a text prompt as a command-line argument, and should return the answer on `stdout` (see <> for more on this subsystem). *`GIT_NAMESPACE`* controls access to namespaced refs, and is equivalent to the `--namespace` flag. This is mostly useful on the server side, where you may want to store multiple forks of a single repository in one repository, only keeping the refs separate. @@ -235,8 +230,8 @@ Here's an example: [source,console] ---- -$ GIT_REFLOG_ACTION="my action" git commit --allow-empty -m 'my message' -[master 9e3d55a] my message +$ GIT_REFLOG_ACTION="my action" git commit --allow-empty -m 'My message' +[master 9e3d55a] My message $ git reflog -1 -9e3d55a HEAD@{0}: my action: my message +9e3d55a HEAD@{0}: my action: My message ---- diff --git a/book/10-git-internals/sections/maintenance.asc b/book/10-git-internals/sections/maintenance.asc index 5d22cfd2f..d4e53081f 100644 --- a/book/10-git-internals/sections/maintenance.asc +++ b/book/10-git-internals/sections/maintenance.asc @@ -6,12 +6,12 @@ This section will cover some of these scenarios. [[_git_gc]] ==== Maintenance -Occasionally, Git automatically runs a command called ``auto gc''. +Occasionally, Git automatically runs a command called "`auto gc`". Most of the time, this command does nothing. However, if there are too many loose objects (objects not in a packfile) or too many packfiles, Git launches a full-fledged `git gc` command. -The ``gc'' stands for garbage collect, and the command does a number of things: it gathers up all the loose objects and places them in packfiles, it consolidates packfiles into one big packfile, and it removes objects that aren't reachable from any commit and are a few months old. +The "`gc`" stands for garbage collect, and the command does a number of things: it gathers up all the loose objects and places them in packfiles, it consolidates packfiles into one big packfile, and it removes objects that aren't reachable from any commit and are a few months old. -You can run auto gc manually as follows: +You can run `auto gc` manually as follows: [source,console] ---- @@ -19,7 +19,7 @@ $ git gc --auto ---- Again, this generally does nothing. -You must have around 7,000 loose objects or more than 50 packfiles for Git to fire up a real gc command. +You must have around 7,000 loose objects or more than 50 packfiles for Git to fire up a real `gc` command. You can modify these limits with the `gc.auto` and `gc.autopacklimit` config settings, respectively. The other thing `gc` will do is pack up your references into a single file. @@ -50,7 +50,7 @@ cac0cab538b970a37ea1e769cbbde608743bc96d refs/tags/v1.0 If you update a reference, Git doesn't edit this file but instead writes a new file to `refs/heads`. To get the appropriate SHA-1 for a given reference, Git checks for that reference in the `refs` directory and then checks the `packed-refs` file as a fallback. -However, if you can't find a reference in the `refs` directory, it's probably in your `packed-refs` file. +So if you can't find a reference in the `refs` directory, it's probably in your `packed-refs` file. Notice the last line of the file, which begins with a `^`. This means the tag directly above is an annotated tag and that line is the commit that the annotated tag points to. @@ -62,17 +62,17 @@ At some point in your Git journey, you may accidentally lose a commit. Generally, this happens because you force-delete a branch that had work on it, and it turns out you wanted the branch after all; or you hard-reset a branch, thus abandoning commits that you wanted something from. Assuming this happens, how can you get your commits back? -Here's an example that hard-resets the master branch in your test repository to an older commit and then recovers the lost commits. +Here's an example that hard-resets the `master` branch in your test repository to an older commit and then recovers the lost commits. First, let's review where your repository is at this point: [source,console] ---- $ git log --pretty=oneline -ab1afef80fac8e34258ff41fc1b867c702daa24b modified repo a bit -484a59275031909e19aadb7c92262719cfcdf19a added repo.rb -1a410efbd13591db07496601ebc7a059dd55cfe9 third commit -cac0cab538b970a37ea1e769cbbde608743bc96d second commit -fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit +ab1afef80fac8e34258ff41fc1b867c702daa24b Modify repo.rb a bit +484a59275031909e19aadb7c92262719cfcdf19a Create repo.rb +1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit +cac0cab538b970a37ea1e769cbbde608743bc96d Second commit +fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit ---- Now, move the `master` branch back to the middle commit: @@ -80,11 +80,11 @@ Now, move the `master` branch back to the middle commit: [source,console] ---- $ git reset --hard 1a410efbd13591db07496601ebc7a059dd55cfe9 -HEAD is now at 1a410ef third commit +HEAD is now at 1a410ef Third commit $ git log --pretty=oneline -1a410efbd13591db07496601ebc7a059dd55cfe9 third commit -cac0cab538b970a37ea1e769cbbde608743bc96d second commit -fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit +1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit +cac0cab538b970a37ea1e769cbbde608743bc96d Second commit +fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit ---- You've effectively lost the top two commits – you have no branch from which those commits are reachable. @@ -101,8 +101,8 @@ You can see where you've been at any time by running `git reflog`: ---- $ git reflog 1a410ef HEAD@{0}: reset: moving to 1a410ef -ab1afef HEAD@{1}: commit: modified repo.rb a bit -484a592 HEAD@{2}: commit: added repo.rb +ab1afef HEAD@{1}: commit: Modify repo.rb a bit +484a592 HEAD@{2}: commit: Create repo.rb ---- Here we can see the two commits that we have had checked out, however there is not much information here. @@ -117,7 +117,7 @@ Reflog message: updating HEAD Author: Scott Chacon Date: Fri May 22 18:22:37 2009 -0700 - third commit + Third commit commit ab1afef80fac8e34258ff41fc1b867c702daa24b Reflog: HEAD@{1} (Scott Chacon ) @@ -125,7 +125,7 @@ Reflog message: updating HEAD Author: Scott Chacon Date: Fri May 22 18:15:24 2009 -0700 - modified repo.rb a bit + Modify repo.rb a bit ---- It looks like the bottom commit is the one you lost, so you can recover it by creating a new branch at that commit. @@ -135,11 +135,11 @@ For example, you can start a branch named `recover-branch` at that commit (ab1af ---- $ git branch recover-branch ab1afef $ git log --pretty=oneline recover-branch -ab1afef80fac8e34258ff41fc1b867c702daa24b modified repo a bit -484a59275031909e19aadb7c92262719cfcdf19a added repo.rb -1a410efbd13591db07496601ebc7a059dd55cfe9 third commit -cac0cab538b970a37ea1e769cbbde608743bc96d second commit -fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit +ab1afef80fac8e34258ff41fc1b867c702daa24b Modify repo.rb a bit +484a59275031909e19aadb7c92262719cfcdf19a Create repo.rb +1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit +cac0cab538b970a37ea1e769cbbde608743bc96d Second commit +fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit ---- Cool – now you have a branch named `recover-branch` that is where your `master` branch used to be, making the first two commits reachable again. @@ -168,7 +168,7 @@ dangling tree aea790b9a58f6cf6f2804eeac9f0abbe9631e4c9 dangling blob 7108f7ecb345ee9d0084193f147cdad4d2998293 ---- -In this case, you can see your missing commit after the string ``dangling commit''. +In this case, you can see your missing commit after the string "`dangling commit`". You can recover it the same way, by adding a branch that points to that SHA-1. [[_removing_objects]] @@ -192,10 +192,10 @@ First, add a large object to your history: [source,console] ---- -$ curl https://www.kernel.org/pub/software/scm/git/git-2.1.0.tar.gz > git.tgz +$ curl -L https://www.kernel.org/pub/software/scm/git/git-2.1.0.tar.gz > git.tgz $ git add git.tgz -$ git commit -m 'add git tarball' -[master 7b30847] add git tarball +$ git commit -m 'Add git tarball' +[master 7b30847] Add git tarball 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 git.tgz ---- @@ -207,8 +207,8 @@ Better get rid of it: ---- $ git rm git.tgz rm 'git.tgz' -$ git commit -m 'oops - removed large tarball' -[master dadf725] oops - removed large tarball +$ git commit -m 'Oops - remove large tarball' +[master dadf725] Oops - remove large tarball 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 git.tgz ---- @@ -278,8 +278,8 @@ You can easily see what commits modified this file: [source,console] ---- $ git log --oneline --branches -- git.tgz -dadf725 oops - removed large tarball -7b30847 add git tarball +dadf725 Oops - remove large tarball +7b30847 Add git tarball ---- You must rewrite all the commits downstream from `7b30847` to fully remove this file from your Git history. diff --git a/book/10-git-internals/sections/objects.asc b/book/10-git-internals/sections/objects.asc index 4aeef0aeb..3182d9f9d 100644 --- a/book/10-git-internals/sections/objects.asc +++ b/book/10-git-internals/sections/objects.asc @@ -126,7 +126,7 @@ The next type of Git object we'll examine is the _tree_, which solves the proble Git stores content in a manner similar to a UNIX filesystem, but a bit simplified. All the content is stored as tree and blob objects, with trees corresponding to UNIX directory entries and blobs corresponding more or less to inodes or file contents. A single tree object contains one or more entries, each of which is the SHA-1 hash of a blob or subtree with its associated mode, type, and filename. -For example, the most recent tree in a project may look something like this: +For example, let's say you have a project where the most-recent tree looks something like: [source,console] ---- @@ -150,15 +150,15 @@ $ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 Depending on what shell you use, you may encounter errors when using the `master^{tree}` syntax. In CMD on Windows, the `^` character is used for escaping, so you have to double it to avoid this: `git cat-file -p master^^{tree}`. -When using PowerShell, parameters using {} characters have to be quoted to avoid the parameter being parsed incorrectly: `git cat-file -p 'master^{tree}'`. +When using PowerShell, parameters using `{}` characters have to be quoted to avoid the parameter being parsed incorrectly: `git cat-file -p 'master^{tree}'`. If you're using ZSH, the `^` character is used for globbing, so you have to enclose the whole expression in quotes: `git cat-file -p "master^{tree}"`. ==== Conceptually, the data that Git is storing looks something like this: -.Simple version of the Git data model. -image::images/data-model-1.png[Simple version of the Git data model.] +.Simple version of the Git data model +image::images/data-model-1.png[Simple version of the Git data model] You can fairly easily create your own tree. Git normally creates a tree by taking the state of your staging area or index and writing a series of tree objects from it. @@ -202,7 +202,7 @@ You'll now create a new tree with the second version of `test.txt` and a new fil [source,console] ---- $ echo 'new file' > new.txt -$ git update-index --add --cacheinfo 100644 \ +$ git update-index --cacheinfo 100644 \ 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt $ git update-index --add new.txt ---- @@ -219,7 +219,7 @@ $ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt ---- -Notice that this tree has both file entries and also that the `test.txt` SHA-1 is the ``version 2'' SHA-1 from earlier (`1f7a7a`). +Notice that this tree has both file entries and also that the `test.txt` SHA-1 is the "`version 2`" SHA-1 from earlier (`1f7a7a`). Just for fun, you'll add the first tree as a subdirectory into this one. You can read trees into your staging area by calling `git read-tree`. In this case, you can read an existing tree into your staging area as a subtree by using the `--prefix` option with this command: @@ -238,8 +238,8 @@ $ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614 If you created a working directory from the new tree you just wrote, you would get the two files in the top level of the working directory and a subdirectory named `bak` that contained the first version of the `test.txt` file. You can think of the data that Git contains for these structures as being like this: -.The content structure of your current Git data. -image::images/data-model-2.png[The content structure of your current Git data.] +.The content structure of your current Git data +image::images/data-model-2.png[The content structure of your current Git data] [[_git_commit_objects]] ==== Commit Objects @@ -253,12 +253,17 @@ Start with the first tree you wrote: [source,console] ---- -$ echo 'first commit' | git commit-tree d8329f +$ echo 'First commit' | git commit-tree d8329f fdf4fc3344e67ab068f836878b6c4951e3b15f3d ---- +[NOTE] +==== You will get a different hash value because of different creation time and author data. +Moreover, while in principle any commit object can be reproduced precisely given that data, historical details of this book's construction mean that the printed commit hashes might not correspond to the given commits. Replace commit and tag hashes with your own checksums further in this chapter. +==== + Now you can look at your new commit object with `git cat-file`: [source,console] @@ -268,18 +273,18 @@ tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 author Scott Chacon 1243040974 -0700 committer Scott Chacon 1243040974 -0700 -first commit +First commit ---- -The format for a commit object is simple: it specifies the top-level tree for the snapshot of the project at that point; the author/committer information (which uses your `user.name` and `user.email` configuration settings and a timestamp); a blank line, and then the commit message. +The format for a commit object is simple: it specifies the top-level tree for the snapshot of the project at that point; the parent commits if any (the commit object described above does not have any parents); the author/committer information (which uses your `user.name` and `user.email` configuration settings and a timestamp); a blank line, and then the commit message. Next, you'll write the other two commit objects, each referencing the commit that came directly before it: [source,console] ---- -$ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3 +$ echo 'Second commit' | git commit-tree 0155eb -p fdf4fc3 cac0cab538b970a37ea1e769cbbde608743bc96d -$ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab +$ echo 'Third commit' | git commit-tree 3c4e9c -p cac0cab 1a410efbd13591db07496601ebc7a059dd55cfe9 ---- @@ -293,7 +298,7 @@ commit 1a410efbd13591db07496601ebc7a059dd55cfe9 Author: Scott Chacon Date: Fri May 22 18:15:24 2009 -0700 - third commit + Third commit bak/test.txt | 1 + 1 file changed, 1 insertion(+) @@ -302,7 +307,7 @@ commit cac0cab538b970a37ea1e769cbbde608743bc96d Author: Scott Chacon Date: Fri May 22 18:14:29 2009 -0700 - second commit + Second commit new.txt | 1 + test.txt | 2 +- @@ -312,7 +317,7 @@ commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d Author: Scott Chacon Date: Fri May 22 18:09:34 2009 -0700 - first commit + First commit test.txt | 1 + 1 file changed, 1 insertion(+) @@ -341,14 +346,14 @@ $ find .git/objects -type f If you follow all the internal pointers, you get an object graph something like this: -.All the reachable objects in your Git directory. -image::images/data-model-3.png[All the reachable objects in your Git directory.] +.All the reachable objects in your Git directory +image::images/data-model-3.png[All the reachable objects in your Git directory] ==== Object Storage We mentioned earlier that there is a header stored with every object you commit to your Git object database. Let's take a minute to see how Git stores its objects. -You'll see how to store a blob object -- in this case, the string ``what is up, doc?'' -- interactively in the Ruby scripting language. +You'll see how to store a blob object -- in this case, the string "`what is up, doc?`" -- interactively in the Ruby scripting language. You can start up interactive Ruby mode with the `irb` command: @@ -360,11 +365,11 @@ $ irb ---- Git first constructs a header which starts by identifying the type of object -- in this case, a blob. -To that first part of the header, Git adds a space followed by the size in bytes of the content, and adding a final null byte: +To that first part of the header, Git adds a space followed by the size in bytes of the content, and adding a final null byte: [source,console] ---- ->> header = "blob #{content.length}\0" +>> header = "blob #{content.bytesize}\0" => "blob 16\u0000" ---- diff --git a/book/10-git-internals/sections/packfiles.asc b/book/10-git-internals/sections/packfiles.asc index d3d84fd4a..d77b8c65d 100644 --- a/book/10-git-internals/sections/packfiles.asc +++ b/book/10-git-internals/sections/packfiles.asc @@ -27,8 +27,8 @@ To demonstrate, we'll add the `repo.rb` file from the Grit library -- this is ab $ curl https://raw.githubusercontent.com/mojombo/grit/master/lib/grit/repo.rb > repo.rb $ git checkout master $ git add repo.rb -$ git commit -m 'added repo.rb' -[master 484a592] added repo.rb +$ git commit -m 'Create repo.rb' +[master 484a592] Create repo.rb 3 files changed, 709 insertions(+), 2 deletions(-) delete mode 100644 bak/test.txt create mode 100644 repo.rb @@ -58,8 +58,8 @@ At this point, modify that file a little, and see what happens: [source,console] ---- $ echo '# testing' >> repo.rb -$ git commit -am 'modified repo.rb a bit' -[master 2431da6] modified repo.rb a bit +$ git commit -am 'Modify repo.rb a bit' +[master 2431da6] Modify repo.rb a bit 1 file changed, 1 insertion(+) ---- @@ -85,8 +85,8 @@ You have two nearly identical 22K objects on your disk (each compressed to appro Wouldn't it be nice if Git could store one of them in full but then the second object only as the delta between it and the first? It turns out that it can. -The initial format in which Git saves objects on disk is called a ``loose'' object format. -However, occasionally Git packs up several of these objects into a single binary file called a ``packfile'' in order to save space and be more efficient. +The initial format in which Git saves objects on disk is called a "`loose`" object format. +However, occasionally Git packs up several of these objects into a single binary file called a "`packfile`" in order to save space and be more efficient. Git does this if you have too many loose objects around, if you run the `git gc` command manually, or if you push to a remote server. To see what happens, you can manually ask Git to pack up the objects by calling the `git gc` command: @@ -112,7 +112,7 @@ $ find .git/objects -type f .git/objects/pack/pack-978e03944f5c581011e6998cd0e9e30000905586.pack ---- -The objects that remain are the blobs that aren't pointed to by any commit -- in this case, the ``what is up, doc?'' example and the ``test content'' example blobs you created earlier. +The objects that remain are the blobs that aren't pointed to by any commit -- in this case, the "`what is up, doc?`" example and the "`test content`" example blobs you created earlier. Because you never added them to any commits, they're considered dangling and aren't packed up in your new packfile. The other files are your new packfile and an index. diff --git a/book/10-git-internals/sections/plumbing-porcelain.asc b/book/10-git-internals/sections/plumbing-porcelain.asc index e7a26a154..53b409554 100644 --- a/book/10-git-internals/sections/plumbing-porcelain.asc +++ b/book/10-git-internals/sections/plumbing-porcelain.asc @@ -3,7 +3,7 @@ This book covers primarily how to use Git with 30 or so subcommands such as `checkout`, `branch`, `remote`, and so on. But because Git was initially a toolkit for a version control system rather than a full user-friendly VCS, it has a number of subcommands that do low-level work and were designed to be chained together UNIX-style or called from scripts. -These commands are generally referred to as Git's ``plumbing'' commands, while the more user-friendly commands are called ``porcelain'' commands. +These commands are generally referred to as Git's "`plumbing`" commands, while the more user-friendly commands are called "`porcelain`" commands. As you will have noticed by now, this book's first nine chapters deal almost exclusively with porcelain commands. But in this chapter, you'll be dealing mostly with the lower-level plumbing commands, because they give you access to the inner workings of Git, and help demonstrate how and why Git does what it does. diff --git a/book/10-git-internals/sections/refs.asc b/book/10-git-internals/sections/refs.asc index 0f7b84bd9..c8319084f 100644 --- a/book/10-git-internals/sections/refs.asc +++ b/book/10-git-internals/sections/refs.asc @@ -4,7 +4,7 @@ If you were interested in seeing the history of your repository reachable from commit, say, `1a410e`, you could run something like `git log 1a410e` to display that history, but you would still have to remember that `1a410e` is the commit you want to use as the starting point for that history. Instead, it would be easier if you had a file in which you could store that SHA-1 value under a simple name so you could use that simple name rather than the raw SHA-1 value. -In Git, these simple names are called ``references'' or ``refs''; you can find the files that contain those SHA-1 values in the `.git/refs` directory. +In Git, these simple names are called "`references`" or "`refs`"; you can find the files that contain those SHA-1 values in the `.git/refs` directory. In the current project, this directory contains no files, but it does contain a simple structure: [source,console] @@ -28,9 +28,9 @@ Now, you can use the head reference you just created instead of the SHA-1 value [source,console] ---- $ git log --pretty=oneline master -1a410efbd13591db07496601ebc7a059dd55cfe9 third commit -cac0cab538b970a37ea1e769cbbde608743bc96d second commit -fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit +1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit +cac0cab538b970a37ea1e769cbbde608743bc96d Second commit +fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit ---- You aren't encouraged to directly edit the reference files; instead, Git provides the safer command `git update-ref` to do this if you want to update a reference: @@ -53,14 +53,14 @@ Your branch will contain only work from that commit down: [source,console] ---- $ git log --pretty=oneline test -cac0cab538b970a37ea1e769cbbde608743bc96d second commit -fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit +cac0cab538b970a37ea1e769cbbde608743bc96d Second commit +fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit ---- Now, your Git database conceptually looks something like this: -.Git directory objects with branch head references included. -image::images/data-model-4.png[Git directory objects with branch head references included.] +.Git directory objects with branch head references included +image::images/data-model-4.png[Git directory objects with branch head references included] When you run commands like `git branch `, Git basically runs that `update-ref` command to add the SHA-1 of the last commit of the branch you're on into whatever new reference you want to create. @@ -70,8 +70,12 @@ When you run commands like `git branch `, Git basically runs that `updat The question now is, when you run `git branch `, how does Git know the SHA-1 of the last commit? The answer is the HEAD file. -The HEAD file is a symbolic reference to the branch you're currently on. -By symbolic reference, we mean that unlike a normal reference, it doesn't generally contain a SHA-1 value but rather a pointer to another reference. +Usually the HEAD file is a symbolic reference to the branch you're currently on. +By symbolic reference, we mean that unlike a normal reference, it contains a pointer to another reference. + +However in some rare cases the HEAD file may contain the SHA-1 value of a Git object. +This happens when you checkout a tag, commit, or remote branch, which puts your repository in https://git-scm.com/docs/git-checkout#_detached_head["detached HEAD"^] state. + If you look at the file, you'll normally see something like this: [source,console] @@ -138,7 +142,7 @@ You can see this by creating an annotated tag (using the `-a` option): [source,console] ---- -$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag' +$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'Test tag' ---- Here's the object SHA-1 value it created: @@ -159,7 +163,7 @@ type commit tag v1.1 tagger Scott Chacon Sat May 23 16:48:58 2009 -0700 -test tag +Test tag ---- Notice that the object entry points to the commit SHA-1 value that you tagged. @@ -201,5 +205,5 @@ ca82a6dff817ec66f44342007202690a93763949 ---- Remote references differ from branches (`refs/heads` references) mainly in that they're considered read-only. -You can `git checkout` to one, but Git won't point HEAD at one, so you'll never update it with a `commit` command. +You can `git checkout` to one, but Git won't symbolically reference HEAD to one, so you'll never update it with a `commit` command. Git manages them as bookmarks to the last known state of where those branches were on those servers. diff --git a/book/10-git-internals/sections/refspec.asc b/book/10-git-internals/sections/refspec.asc index 8d1f78074..f8157ce56 100644 --- a/book/10-git-internals/sections/refspec.asc +++ b/book/10-git-internals/sections/refspec.asc @@ -75,14 +75,14 @@ If you want to always fetch the `master` and `experiment` branches from the `ori fetch = +refs/heads/experiment:refs/remotes/origin/experiment ---- -You can't use partial globs in the pattern, so this would be invalid: +Since Git 2.6.0 you can use partial globs in the pattern to match multiple branches, so this works: [source,ini] ---- fetch = +refs/heads/qa*:refs/remotes/origin/qa* ---- -However, you can use namespaces (or directories) to accomplish something like that. +Even better, you can use namespaces (or directories) to accomplish the same with more structure. If you have a QA team that pushes a series of branches, and you want to get the `master` branch and any of the QA team's branches but nothing else, you can use a config section like this: [source,ini] @@ -101,7 +101,7 @@ If you have a complex workflow process that has a QA team pushing branches, deve It's nice that you can fetch namespaced references that way, but how does the QA team get their branches into a `qa/` namespace in the first place? You accomplish that by using refspecs to push. -If the QA team wants to push their `master` branch to `qa/master` on the remote server, they can run +If the QA team wants to push their `master` branch to `qa/master` on the remote server, they can run: [source,console] ---- diff --git a/book/10-git-internals/sections/transfer-protocols.asc b/book/10-git-internals/sections/transfer-protocols.asc index 93fb867ca..44e6a39ad 100644 --- a/book/10-git-internals/sections/transfer-protocols.asc +++ b/book/10-git-internals/sections/transfer-protocols.asc @@ -1,12 +1,12 @@ === Transfer Protocols -Git can transfer data between two repositories in two major ways: the ``dumb'' protocol and the ``smart'' protocol. +Git can transfer data between two repositories in two major ways: the "`dumb`" protocol and the "`smart`" protocol. This section will quickly cover how these two main protocols operate. ==== The Dumb Protocol If you're setting up a repository to be served read-only over HTTP, the dumb protocol is likely what will be used. -This protocol is called ``dumb'' because it requires no Git-specific code on the server side during the transport process; the fetch process is a series of HTTP `GET` requests, where the client can assume the layout of the Git repository on the server. +This protocol is called "`dumb`" because it requires no Git-specific code on the server side during the transport process; the fetch process is a series of HTTP `GET` requests, where the client can assume the layout of the Git repository on the server. [NOTE] ==== @@ -61,7 +61,7 @@ parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 author Scott Chacon 1205815931 -0700 committer Scott Chacon 1240030591 -0700 -changed the version number +Change version number ---- Next, you have two more objects to retrieve – `cfda3b`, which is the tree of content that the commit we just retrieved points to; and `085bb3`, which is the parent commit: @@ -153,9 +153,11 @@ $ ssh -x git@server "git-receive-pack 'simplegit-progit.git'" The `git-receive-pack` command immediately responds with one line for each reference it currently has – in this case, just the `master` branch and its SHA-1. The first line also has a list of the server's capabilities (here, `report-status`, `delete-refs`, and some others, including the client identifier). -Each line starts with a 4-character hex value specifying how long the rest of the line is. -Your first line starts with 00a5, which is hexadecimal for 165, meaning that 165 bytes remain on that line. -The next line is 0000, meaning the server is done with its references listing. +The data is transmitted in chunks. +Each chunk starts with a 4-character hex value specifying how long the chunk is (including the 4 bytes of the length itself). +Chunks usually contain a single line of data and a trailing linefeed. +Your first chunk starts with 00a5, which is hexadecimal for 165, meaning the chunk is 165 bytes long. +The next chunk is 0000, meaning the server is done with its references listing. Now that it knows the server's state, your `send-pack` process determines what commits it has that the server doesn't. For each reference that this push will update, the `send-pack` process tells the `receive-pack` process that information. @@ -172,7 +174,7 @@ For instance, if you're updating the `master` branch and adding an `experiment` Git sends a line for each reference you're updating with the line's length, the old SHA-1, the new SHA-1, and the reference that is being updated. The first line also has the client's capabilities. -The SHA-1 value of all '0's means that nothing was there before – because you're adding the experiment reference. +The SHA-1 value of all '0's means that nothing was there before – because you're adding the `experiment` reference. If you were deleting a reference, you would see the opposite: all '0's on the right side. Next, the client sends a packfile of all the objects the server doesn't have yet. @@ -209,6 +211,8 @@ The client then makes another request, this time a `POST`, with the data that `s The `POST` request includes the `send-pack` output and the packfile as its payload. The server then indicates success or failure with its HTTP response. +Keep in mind the HTTP protocol may further wrap this data inside a chunked transfer encoding. + ===== Downloading Data (((git commands, fetch-pack)))(((git commands, upload-pack))) @@ -239,9 +243,9 @@ After `fetch-pack` connects, `upload-pack` sends back something like this: This is very similar to what `receive-pack` responds with, but the capabilities are different. In addition, it sends back what HEAD points to (`symref=HEAD:refs/heads/master`) so the client knows what to check out if this is a clone. -At this point, the `fetch-pack` process looks at what objects it has and responds with the objects that it needs by sending ``want'' and then the SHA-1 it wants. -It sends all the objects it already has with ``have'' and then the SHA-1. -At the end of this list, it writes ``done'' to initiate the `upload-pack` process to begin sending the packfile of the data it needs: +At this point, the `fetch-pack` process looks at what objects it has and responds with the objects that it needs by sending "`want`" and then the SHA-1 it wants. +It sends all the objects it already has with "`have`" and then the SHA-1. +At the end of this list, it writes "`done`" to initiate the `upload-pack` process to begin sending the packfile of the data it needs: [source] ---- diff --git a/book/A-git-in-other-environments/sections/bash.asc b/book/A-git-in-other-environments/sections/bash.asc index e680b7163..629d2945c 100644 --- a/book/A-git-in-other-environments/sections/bash.asc +++ b/book/A-git-in-other-environments/sections/bash.asc @@ -4,13 +4,14 @@ If you're a Bash user, you can tap into some of your shell's features to make your experience with Git a lot friendlier. Git actually ships with plugins for several shells, but it's not turned on by default. -First, you need to get a copy of the `contrib/completion/git-completion.bash` file out of the Git source code. -Copy it somewhere handy, like your home directory, and add this to your `.bashrc`: +First, you need to get a copy of the completions file from the source code of the Git release you're using. +Check your version by typing `git version`, then use `git checkout tags/vX.Y.Z`, where `vX.Y.Z` corresponds to the version of Git you are using. +Copy the `contrib/completion/git-completion.bash` file somewhere handy, like your home directory, and add this to your `.bashrc`: [source,console] ------ +---- . ~/git-completion.bash ------ +---- Once that's done, change your directory to a Git repository, and type: @@ -27,16 +28,16 @@ This can be as simple or complex as you want, but there are generally a few key To add these to your prompt, just copy the `contrib/completion/git-prompt.sh` file from Git's source repository to your home directory, add something like this to your `.bashrc`: [source,console] ------ +---- . ~/git-prompt.sh export GIT_PS1_SHOWDIRTYSTATE=1 export PS1='\w$(__git_ps1 " (%s)")\$ ' ------ +---- The `\w` means print the current working directory, the `\$` prints the `$` part of the prompt, and `__git_ps1 " (%s)"` calls the function provided by `git-prompt.sh` with a formatting argument. Now your bash prompt will look like this when you're anywhere inside a Git-controlled project: -.Customized `bash` prompt. -image::images/git-bash.png[Customized `bash` prompt.] +.Customized `bash` prompt +image::images/git-bash.png[Customized `bash` prompt] Both of these scripts come with helpful documentation; take a look at the contents of `git-completion.bash` and `git-prompt.sh` for more information. diff --git a/book/A-git-in-other-environments/sections/eclipse.asc b/book/A-git-in-other-environments/sections/eclipse.asc deleted file mode 100644 index 76cfd9c5f..000000000 --- a/book/A-git-in-other-environments/sections/eclipse.asc +++ /dev/null @@ -1,10 +0,0 @@ -=== Git in Eclipse - -(((Eclipse))) -Eclipse ships with a plugin called Egit, which provides a fairly-complete interface to Git operations. -It's accessed by switching to the Git Perspective (Window > Open Perspective > Other…, and select "Git"). - -.Eclipse's EGit environment. -image::images/egit.png[Eclipse's EGit environment.] - -EGit comes with plenty of great documentation, which you can find by going to Help > Help Contents, and choosing the "EGit Documentation" node from the contents listing. diff --git a/book/A-git-in-other-environments/sections/guis.asc b/book/A-git-in-other-environments/sections/guis.asc index 966d98638..3c2b62903 100644 --- a/book/A-git-in-other-environments/sections/guis.asc +++ b/book/A-git-in-other-environments/sections/guis.asc @@ -7,7 +7,7 @@ But plain text isn't the best choice for all tasks; sometimes a visual represent It's important to note that different interfaces are tailored for different workflows. Some clients expose only a carefully curated subset of Git functionality, in order to support a specific way of working that the author considers effective. -When viewed in this light, none of these tools can be called ``better'' than any of the others, they're simply more fit for their intended purpose. +When viewed in this light, none of these tools can be called "`better`" than any of the others, they're simply more fit for their intended purpose. Also note that there's nothing these graphical clients can do that the command-line client can't; the command-line is still where you'll have the most power and control when working with your repositories. ==== `gitk` and `git-gui` @@ -28,11 +28,11 @@ $ gitk [git log options] ---- Gitk accepts many command-line options, most of which are passed through to the underlying `git log` action. -Probably one of the most useful is the `--all` flag, which tells gitk to show commits reachable from _any_ ref, not just HEAD. +Probably one of the most useful is the `--all` flag, which tells `gitk` to show commits reachable from _any_ ref, not just HEAD. Gitk's interface looks like this: -.The `gitk` history viewer. -image::images/gitk.png[The `gitk` history viewer.] +.The `gitk` history viewer +image::images/gitk.png[The `gitk` history viewer] On the top is something that looks a bit like the output of `git log --graph`; each dot represents a commit, the lines represent parent relationships, and refs are shown as colored boxes. The yellow dot represents HEAD, and the red dot represents changes that are yet to become a commit. @@ -43,14 +43,14 @@ In between is a collection of controls used for searching history. It, too, is easiest to invoke from the command line: [source,console] ------ +---- $ git gui ------ +---- And it looks something like this: -.The `git-gui` commit tool. -image::images/git-gui.png[The `git-gui` commit tool.] +.The `git-gui` commit tool +image::images/git-gui.png[The `git-gui` commit tool] On the left is the index; unstaged changes are on top, staged changes on the bottom. You can move entire files between the two states by clicking on their icons, or you can select a file for viewing by clicking on its name. @@ -59,9 +59,9 @@ At top right is the diff view, which shows the changes for the currently-selecte You can stage individual hunks (or individual lines) by right-clicking in this area. At the bottom right is the message and action area. -Type your message into the text box and click ``Commit'' to do something similar to `git commit`. -You can also choose to amend the last commit by choosing the ``Amend'' radio button, which will update the ``Staged Changes'' area with the contents of the last commit. -Then you can simply stage or unstage some changes, alter the commit message, and click ``Commit'' again to replace the old commit with a new one. +Type your message into the text box and click "`Commit`" to do something similar to `git commit`. +You can also choose to amend the last commit by choosing the "`Amend`" radio button, which will update the "`Staged Changes`" area with the contents of the last commit. +Then you can simply stage or unstage some changes, alter the commit message, and click "`Commit`" again to replace the old commit with a new one. `gitk` and `git-gui` are examples of task-oriented tools. Each of them is tailored for a specific purpose (viewing history and creating commits, respectively), and omit the features not necessary for that task. @@ -73,20 +73,20 @@ GitHub has created two workflow-oriented Git clients: one for Windows, and one f These clients are a good example of workflow-oriented tools – rather than expose _all_ of Git's functionality, they instead focus on a curated set of commonly-used features that work well together. They look like this: -.GitHub for macOS. -image::images/github_mac.png[GitHub for macOS.] +.GitHub for macOS +image::images/github_mac.png[GitHub for macOS] -.GitHub for Windows. -image::images/github_win.png[GitHub for Windows.] +.GitHub for Windows +image::images/github_win.png[GitHub for Windows] They are designed to look and work very much alike, so we'll treat them like a single product in this chapter. -We won't be doing a detailed rundown of these tools (they have their own documentation), but a quick tour of the ``changes'' view (which is where you'll spend most of your time) is in order. +We won't be doing a detailed rundown of these tools (they have their own documentation), but a quick tour of the "`changes`" view (which is where you'll spend most of your time) is in order. -* On the left is the list of repositories the client is tracking; you can add a repository (either by cloning or attaching locally) by clicking the ``+'' icon at the top of this area. +* On the left is the list of repositories the client is tracking; you can add a repository (either by cloning or attaching locally) by clicking the "`+`" icon at the top of this area. * In the center is a commit-input area, which lets you input a commit message, and select which files should be included. - (On Windows, the commit history is displayed directly below this; on macOS, it's on a separate tab.) + On Windows, the commit history is displayed directly below this; on macOS, it's on a separate tab. * On the right is a diff view, which shows what's changed in your working directory, or which changes were included in the selected commit. -* The last thing to notice is the ``Sync'' button at the top-right, which is the primary way you interact over the network. +* The last thing to notice is the "`Sync`" button at the top-right, which is the primary way you interact over the network. [NOTE] ==== @@ -96,10 +96,10 @@ While they're designed to highlight GitHub's service and recommended workflow, t ===== Installation -GitHub for Windows can be downloaded from https://windows.github.com[], and GitHub for macOS from https://mac.github.com[]. +GitHub for Windows and macOS can be downloaded from https://desktop.github.com/[^]. When the applications are first run, they walk you through all the first-time Git setup, such as configuring your name and email address, and both set up sane defaults for many common configuration options, such as credential caches and CRLF behavior. -Both are ``evergreen'' – updates are downloaded and installed in the background while the applications are open. +Both are "`evergreen`" – updates are downloaded and installed in the background while the applications are open. This helpfully includes a bundled version of Git, which means you probably won't have to worry about manually updating it again. On Windows, the client includes a shortcut to launch PowerShell with Posh-git, which we'll talk more about later in this chapter. @@ -110,25 +110,25 @@ If you already have a local repository, just drag its directory from the Finder ===== Recommended Workflow Once it's installed and configured, you can use the GitHub client for many common Git tasks. -The intended workflow for this tool is sometimes called the ``GitHub Flow.'' +The intended workflow for this tool is sometimes called the "`GitHub Flow.`" We cover this in more detail in <>, but the general gist is that (a) you'll be committing to a branch, and (b) you'll be syncing up with a remote repository fairly regularly. Branch management is one of the areas where the two tools diverge. On macOS, there's a button at the top of the window for creating a new branch: -.``Create Branch'' button on macOS. -image::images/branch_widget_mac.png[``Create Branch'' button on macOS.] +."`Create Branch`" button on macOS +image::images/branch_widget_mac.png[“Create Branch” button on macOS] On Windows, this is done by typing the new branch's name in the branch-switching widget: -.Creating a branch on Windows. -image::images/branch_widget_win.png[Creating a branch on Windows.] +.Creating a branch on Windows +image::images/branch_widget_win.png[Creating a branch on Windows] Once your branch is created, making new commits is fairly straightforward. Make some changes in your working directory, and when you switch to the GitHub client window, it will show you which files changed. -Enter a commit message, select the files you'd like to include, and click the ``Commit'' button (ctrl-enter or ⌘-enter). +Enter a commit message, select the files you'd like to include, and click the "`Commit`" button (ctrl-enter or ⌘-enter). -The main way you interact with other repositories over the network is through the ``Sync'' feature. +The main way you interact with other repositories over the network is through the "`Sync`" feature. Git internally has separate operations for pushing, fetching, merging, and rebasing, but the GitHub clients collapse all of these into one multi-step feature. Here's what happens when you click the Sync button: @@ -144,9 +144,8 @@ These tools are very well-suited for the workflow they're designed for. Developers and non-developers alike can be collaborating on a project within minutes, and many of the best practices for this kind of workflow are baked into the tools. However, if your workflow is different, or you want more control over how and when network operations are done, we recommend you use another client or the command line. - ==== Other GUIs There are a number of other graphical Git clients, and they run the gamut from specialized, single-purpose tools all the way to apps that try to expose everything Git can do. -The official Git website has a curated list of the most popular clients at https://git-scm.com/downloads/guis[]. -A more comprehensive list is available on the Git wiki site, at https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Graphical_Interfaces[]. +The official Git website has a curated list of the most popular clients at https://git-scm.com/downloads/guis[^]. +A more comprehensive list is available on the Git wiki site, at https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools.html#Graphical_Interfaces[^]. diff --git a/book/A-git-in-other-environments/sections/jetbrainsides.asc b/book/A-git-in-other-environments/sections/jetbrainsides.asc new file mode 100644 index 000000000..1def4a3ed --- /dev/null +++ b/book/A-git-in-other-environments/sections/jetbrainsides.asc @@ -0,0 +1,11 @@ +=== Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine + +(((JetBrains))) +JetBrains IDEs (such as IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, RubyMine, and others) ship with a Git Integration plugin. +It provides a dedicated view in the IDE to work with Git and GitHub Pull Requests. + +.Version Control ToolWindow in JetBrains IDEs +image::images/jb.png[Version Control ToolWindow in JetBrains IDEs] + +The integration relies on the command-line Git client, and requires one to be installed. +The official documentation is available at https://www.jetbrains.com/help/idea/using-git-integration.html[^]. diff --git a/book/A-git-in-other-environments/sections/powershell.asc b/book/A-git-in-other-environments/sections/powershell.asc index d6f5e68d7..e51fe0d57 100644 --- a/book/A-git-in-other-environments/sections/powershell.asc +++ b/book/A-git-in-other-environments/sections/powershell.asc @@ -1,43 +1,50 @@ [[_git_powershell]] === Git in PowerShell -(((powershell)))(((tab completion, powershell)))(((shell prompts, powershell))) +(((PowerShell)))(((tab completion, PowerShell)))(((shell prompts, PowerShell))) (((posh-git))) The legacy command-line terminal on Windows (`cmd.exe`) isn't really capable of a customized Git experience, but if you're using PowerShell, you're in luck. This also works if you're running PowerShell Core on Linux or macOS. -A package called posh-git (https://github.com/dahlbyk/posh-git[]) provides powerful tab-completion facilities, as well as an enhanced prompt to help you stay on top of your repository status. +A package called posh-git (https://github.com/dahlbyk/posh-git[^]) provides powerful tab-completion facilities, as well as an enhanced prompt to help you stay on top of your repository status. It looks like this: -.PowerShell with Posh-git. -image::images/posh-git.png[PowerShell with Posh-git.] +.PowerShell with Posh-git +image::images/posh-git.png[PowerShell with Posh-git] ==== Installation + ===== Prerequisites (Windows only) -Before you're able to run PowerShell scripts on your machine, you need to set your local ExecutionPolicy to RemoteSigned (Basically anything except Undefined and Restricted). -If you choose AllSigned instead of RemoteSigned, also local scripts (your own) need to be digitally signed in order to be executed. -With RemoteSigned, only Scripts having the "ZoneIdentifier" set to Internet (were downloaded from the web) need to be signed, others not. -If you're an administrator and want to set it for all Users on that machine, use "-Scope LocalMachine". -If you're a normal user, without administrative rights, you can use "-Scope CurrentUser" to set it only for you. -More about PowerShell Scopes: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes[] +Before you're able to run PowerShell scripts on your machine, you need to set your local `ExecutionPolicy` to `RemoteSigned` (basically, anything except `Undefined` and `Restricted`). +If you choose `AllSigned` instead of `RemoteSigned`, also local scripts (your own) need to be digitally signed in order to be executed. +With `RemoteSigned`, only scripts having the `ZoneIdentifier` set to `Internet` (were downloaded from the web) need to be signed, others not. +If you're an administrator and want to set it for all users on that machine, use `-Scope LocalMachine`. +If you're a normal user, without administrative rights, you can use `-Scope CurrentUser` to set it only for you. + +More about PowerShell Scopes: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes[^]. + +More about PowerShell ExecutionPolicy: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy[^]. -More about PowerShell ExecutionPolicy: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy[] +To set the value of `ExecutionPolicy` to `RemoteSigned` for all users use the next command: [source,powershell] ------ +---- > Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force ------ +---- ===== PowerShell Gallery + If you have at least PowerShell 5 or PowerShell 4 with PackageManagement installed, you can use the package manager to install posh-git for you. -More information about PowerShell Gallery: https://docs.microsoft.com/en-us/powershell/gallery/overview[] +More information about PowerShell Gallery: https://learn.microsoft.com/en-us/powershell/scripting/gallery/overview[^]. + [source,powershell] ------ +---- > Install-Module posh-git -Scope CurrentUser -Force > Install-Module posh-git -Scope CurrentUser -AllowPrerelease -Force # Newer beta version with PowerShell Core support ------ -If you want to install posh-git for all users, use "-Scope AllUsers" instead and execute the command from an elevated PowerShell console. +---- + +If you want to install posh-git for all users, use `-Scope AllUsers` instead and execute the command from an elevated PowerShell console. If the second command fails with an error like `Module 'PowerShellGet' was not installed by using Install-Module`, you'll need to run another command first: [source,powershell] @@ -49,26 +56,31 @@ Then you can go back and try again. This happens, because the modules that ship with Windows PowerShell are signed with a different publishment certificate. ===== Update PowerShell Prompt -To include git information in your prompt, the posh-git module needs to be imported. -To have posh-git imported every time PowerShell starts, execute the Add-PoshGitToProfile command which will add the import statement into you $profile script. + +To include Git information in your prompt, the posh-git module needs to be imported. +To have posh-git imported every time PowerShell starts, execute the `Add-PoshGitToProfile` command which will add the import statement into your `$profile` script. This script is executed everytime you open a new PowerShell console. -Keep in mind, that there are multiple $profile scripts. -E. g. one for the console and a separate one for the ISE. +Keep in mind, that there are multiple `$profile` scripts. +E.g. one for the console and a separate one for the ISE. + [source,powershell] ------ +---- > Import-Module posh-git > Add-PoshGitToProfile -AllHosts ------ +---- ===== From Source -Just download a posh-git release from (https://github.com/dahlbyk/posh-git[]), and uncompress it. -Then import the module using the full path to the posh-git.psd1 file: + +Just download a posh-git release from https://github.com/dahlbyk/posh-git/releases[^], and uncompress it. +Then import the module using the full path to the `posh-git.psd1` file: + [source,powershell] ------ +---- > Import-Module \src\posh-git.psd1 > Add-PoshGitToProfile -AllHosts ------ +---- This will add the proper line to your `profile.ps1` file, and posh-git will be active the next time you open PowerShell. -For a description of the Git status summary information displayed in the prompt see: https://github.com/dahlbyk/posh-git/blob/master/README.md#git-status-summary-information[] -For more details on how to customize your posh-git prompt see: https://github.com/dahlbyk/posh-git/blob/master/README.md#customization-variables[] + +For a description of the Git status summary information displayed in the prompt see: https://github.com/dahlbyk/posh-git/blob/master/README.md#git-status-summary-information[^] +For more details on how to customize your posh-git prompt see: https://github.com/dahlbyk/posh-git/blob/master/README.md#customization-variables[^]. diff --git a/book/A-git-in-other-environments/sections/sublimetext.asc b/book/A-git-in-other-environments/sections/sublimetext.asc index eded27be9..d62eff430 100644 --- a/book/A-git-in-other-environments/sections/sublimetext.asc +++ b/book/A-git-in-other-environments/sections/sublimetext.asc @@ -1,14 +1,16 @@ === Git in Sublime Text -From version 3.2 onwards, Sublime Text has git integration in the editor. +(((Sublime Text))) +From version 3.2 onwards, Sublime Text has Git integration in the editor. The features are: -* The sidebar will show the git status of files and folders with a badge/icon. -* Files and folders that are in your .gitignore file will be faded out in the sidebar. -* In the status bar, you can see the current git branch and how many modifications you have made. +* The sidebar will show the `git status` of files and folders with a badge/icon. +* Files and folders that are in your `.gitignore` file will be faded out in the sidebar. +* In the status bar, you can see the current Git branch and how many modifications you have made. * All changes to a file are now visible via markers in the gutter. -* You can use part of the Sublime Merge git client functionality from within Sublime Text. - (This requires that Sublime Merge is installed. See: https://www.sublimemerge.com/[]) +* You can use part of the Sublime Merge Git client functionality from within Sublime Text. + This requires that Sublime Merge is installed. + See: https://www.sublimemerge.com/[^]. -The official documentation for Sublime Text can be found here: https://www.sublimetext.com/docs/3/git_integration.html[] \ No newline at end of file +The official documentation for Sublime Text can be found here: https://www.sublimetext.com/docs/git_integration.html[^]. diff --git a/book/A-git-in-other-environments/sections/visualstudio.asc b/book/A-git-in-other-environments/sections/visualstudio.asc index 8ab664360..f46d575d0 100644 --- a/book/A-git-in-other-environments/sections/visualstudio.asc +++ b/book/A-git-in-other-environments/sections/visualstudio.asc @@ -1,25 +1,18 @@ === Git in Visual Studio (((Visual Studio))) -Starting with Visual Studio 2013 Update 1, Visual Studio users have a Git client built directly into their IDE. -Visual Studio has had source-control integration features for quite some time, but they were oriented towards centralized, file-locking systems, and Git was not a good match for this workflow. -Visual Studio 2013's Git support has been separated from this older feature, and the result is a much better fit between Studio and Git. +Visual Studio has Git tooling built directly into the IDE, starting with Visual Studio 2019 version 16.8. -To locate the feature, open a project that's controlled by Git (or just `git init` an existing project), and select View > Team Explorer from the menu. -You'll see the "Connect" view, which looks a bit like this: +The tooling supports the following Git functionality: -.Connecting to a Git repository from Team Explorer. -image::images/vs-1.png[Connecting to a Git repository from Team Explorer.] +* Create or clone a repository. +* Open and browse history of a repository. +* Create and checkout branches and tags. +* Stash, stage, and commit changes. +* Fetch, pull, push, or sync commits. +* Merge and rebase branches. +* Resolve merge conflicts. +* View diffs. +* ... and more! -Visual Studio remembers all of the projects you've opened that are Git-controlled, and they're available in the list at the bottom. -If you don't see the one you want there, click the "Add" link and type in the path to the working directory. -Double clicking on one of the local Git repositories leads you to the Home view, which looks like <>. -This is a hub for performing Git actions; when you're _writing_ code, you'll probably spend most of your time in the "Changes" view, but when it comes time to pull down changes made by your teammates, you'll use the "Unsynced Commits" and "Branches" views. - -[[vs_home]] -.The "Home" view for a Git repository in Visual Studio. -image::images/vs-2.png[The Home view for a Git repository in Visual Studio.] - -Visual Studio now has a powerful task-focused UI for Git. -It includes a linear history view, a diff viewer, remote commands, and many other capabilities. -For complete documentation of this feature (which doesn't fit here), go to http://msdn.microsoft.com/en-us/library/hh850437.aspx[]. +Read the https://learn.microsoft.com/en-us/visualstudio/version-control/[official documentation^] to learn more. diff --git a/book/A-git-in-other-environments/sections/visualstudiocode.asc b/book/A-git-in-other-environments/sections/visualstudiocode.asc index 31e8de201..7a646c3b5 100644 --- a/book/A-git-in-other-environments/sections/visualstudiocode.asc +++ b/book/A-git-in-other-environments/sections/visualstudiocode.asc @@ -1,7 +1,8 @@ === Git in Visual Studio Code -Visual Studio Code has git support built in. -You will need to have git version 2.0.0 (or newer) installed. +(((Visual Studio Code))) +Visual Studio Code has Git support built in. +You will need to have Git version 2.0.0 (or newer) installed. The main features are: @@ -15,7 +16,7 @@ The main features are: ** Push/pull/sync with a remote branch. ** Resolve merge conflicts. ** View diffs. -* With a extension, you can also handle GitHub Pull Requests: - https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github[] +* With an extension, you can also handle GitHub Pull Requests: + https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github[^]. -The official documentation can be found here: https://code.visualstudio.com/Docs/editor/versioncontrol[] +The official documentation can be found here: https://code.visualstudio.com/docs/sourcecontrol/overview[^]. diff --git a/book/A-git-in-other-environments/sections/zsh.asc b/book/A-git-in-other-environments/sections/zsh.asc index 2d9c80e6b..c0578a95c 100644 --- a/book/A-git-in-other-environments/sections/zsh.asc +++ b/book/A-git-in-other-environments/sections/zsh.asc @@ -28,30 +28,28 @@ autoload -Uz vcs_info precmd_vcs_info() { vcs_info } precmd_functions+=( precmd_vcs_info ) setopt prompt_subst -RPROMPT=\$vcs_info_msg_0_ -# PROMPT=\$vcs_info_msg_0_'%# ' +RPROMPT='${vcs_info_msg_0_}' +# PROMPT='${vcs_info_msg_0_}%# ' zstyle ':vcs_info:git:*' formats '%b' ---- This results in a display of the current branch on the right-hand side of the terminal window, whenever your shell is inside a Git repository. -(The left side is supported as well, of course; just uncomment the assignment to PROMPT.) +The left side is supported as well, of course; just uncomment the assignment to `PROMPT`. It looks a bit like this: -.Customized `zsh` prompt. -image::images/zsh-prompt.png[Customized `zsh` prompt.] +.Customized `zsh` prompt +image::images/zsh-prompt.png[Customized `zsh` prompt] -For more information on vcs_info, check out its documentation - in the `zshcontrib(1)` manual page, - or online at http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Version-Control-Information[]. +For more information on `vcs_info`, check out its documentation in the `zshcontrib(1)` manual page, or online at https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#Version-Control-Information[^]. -Instead of vcs_info, you might prefer the prompt customization script that ships with Git, called `git-prompt.sh`; see https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh[] for details. +Instead of `vcs_info`, you might prefer the prompt customization script that ships with Git, called `git-prompt.sh`; see https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh[^] for details. `git-prompt.sh` is compatible with both Bash and Zsh. Zsh is powerful enough that there are entire frameworks dedicated to making it better. -One of them is called "oh-my-zsh", and it can be found at https://github.com/robbyrussell/oh-my-zsh[]. -oh-my-zsh's plugin system comes with powerful git tab-completion, and it has a variety of prompt "themes", many of which display version-control data. +One of them is called "oh-my-zsh", and it can be found at https://github.com/ohmyzsh/ohmyzsh[^]. +oh-my-zsh's plugin system comes with powerful Git tab-completion, and it has a variety of prompt "themes", many of which display version-control data. <> is just one example of what can be done with this system. [[oh_my_zsh_git]] -.An example of an oh-my-zsh theme. -image::images/zsh-oh-my.png[An example of an oh-my-zsh theme.] +.An example of an oh-my-zsh theme +image::images/zsh-oh-my.png[An example of an oh-my-zsh theme] diff --git a/book/B-embedding-git/callouts/1.pdf b/book/B-embedding-git/callouts/1.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/10.pdf b/book/B-embedding-git/callouts/10.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/2.pdf b/book/B-embedding-git/callouts/2.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/3.pdf b/book/B-embedding-git/callouts/3.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/4.pdf b/book/B-embedding-git/callouts/4.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/5.pdf b/book/B-embedding-git/callouts/5.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/6.pdf b/book/B-embedding-git/callouts/6.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/7.pdf b/book/B-embedding-git/callouts/7.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/8.pdf b/book/B-embedding-git/callouts/8.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/callouts/9.pdf b/book/B-embedding-git/callouts/9.pdf old mode 100755 new mode 100644 diff --git a/book/B-embedding-git/sections/dulwich.asc b/book/B-embedding-git/sections/dulwich.asc index deaa26fd4..62cab9506 100644 --- a/book/B-embedding-git/sections/dulwich.asc +++ b/book/B-embedding-git/sections/dulwich.asc @@ -2,16 +2,16 @@ (((Dulwich)))(((Python))) There is also a pure-Python Git implementation - Dulwich. -The project is hosted under https://www.dulwich.io/ -It aims to provide an interface to git repositories (both local and remote) that doesn't call out to git directly but instead uses pure Python. +The project is hosted under https://www.dulwich.io/[^]. +It aims to provide an interface to Git repositories (both local and remote) that doesn't call out to Git directly but instead uses pure Python. It has an optional C extensions though, that significantly improve the performance. -Dulwich follows git design and separate two basic levels of API: plumbing and porcelain. +Dulwich follows Git design and separate two basic levels of API: plumbing and porcelain. Here is an example of using the lower level API to access the commit message of the last commit: [source, python] ------ +---- from dulwich.repo import Repo r = Repo('.') r.head() @@ -23,22 +23,20 @@ c c.message # 'Add note about encoding.\n' ------ +---- To print a commit log using high-level porcelain API, one can use: [source, python] ------ +---- from dulwich import porcelain porcelain.log('.', max_entries=1) #commit: 57fbe010446356833a6ad1600059d80b1e731e15 #Author: Jelmer Vernooij #Date: Sat Apr 29 2017 23:57:34 +0000 ------ - +---- ==== Further Reading - * The official API documentation is available at https://www.dulwich.io/apidocs/dulwich.html[] - * Official tutorial at https://www.dulwich.io/docs/tutorial[] has many examples of how to do specific tasks with Dulwich +The API documentation, tutorial, and many examples of how to do specific tasks with Dulwich are available on the official website https://www.dulwich.io[^]. diff --git a/book/B-embedding-git/sections/go-git.asc b/book/B-embedding-git/sections/go-git.asc index b83ca4b96..a477cf1bd 100644 --- a/book/B-embedding-git/sections/go-git.asc +++ b/book/B-embedding-git/sections/go-git.asc @@ -5,25 +5,24 @@ In case you want to integrate Git into a service written in Golang, there also i This implementation does not have any native dependencies and thus is not prone to manual memory management errors. It is also transparent for the standard Golang performance analysis tooling like CPU, Memory profilers, race detector, etc. -go-git is focused on extensibility, compatibility and supports most of the plumbing APIs, which is documented at https://github.com/src-d/go-git/blob/master/COMPATIBILITY.md[]. +go-git is focused on extensibility, compatibility and supports most of the plumbing APIs, which is documented at https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md[^]. Here is a basic example of using Go APIs: [source, go] ------ -import "gopkg.in/src-d/go-git.v4" +---- +import "github.com/go-git/go-git/v5" r, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{ - URL: "https://github.com/src-d/go-git", + URL: "https://github.com/go-git/go-git", Progress: os.Stdout, }) ------ +---- As soon as you have a `Repository` instance, you can access information and perform mutations on it: - [source, go] ------ +---- // retrieves the branch pointed by HEAD ref, err := r.Head() @@ -37,8 +36,7 @@ history, err := commit.History() for _, c := range history { fmt.Println(c) } ------ - +---- ==== Advanced Functionality @@ -46,30 +44,30 @@ go-git has few notable advanced features, one of which is a pluggable storage sy The default implementation is in-memory storage, which is very fast. [source, go] ------ +---- r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{ - URL: "https://github.com/src-d/go-git", + URL: "https://github.com/go-git/go-git", }) ------ +---- Pluggable storage provides many interesting options. -For instance, https://github.com/src-d/go-git/tree/master/_examples/storage[] allows you to store references, objects, and configuration in an Aerospike database. +For instance, https://github.com/go-git/go-git/tree/master/_examples/storage[^] allows you to store references, objects, and configuration in an Aerospike database. Another feature is a flexible filesystem abstraction. -Using https://godoc.org/github.com/src-d/go-billy#Filesystem[] it is easy to store all the files in different way i.e by packing all of them to a single archive on disk or by keeping them all in-memory. +Using https://pkg.go.dev/github.com/go-git/go-billy/v5?tab=doc#Filesystem[^] it is easy to store all the files in different way i.e by packing all of them to a single archive on disk or by keeping them all in-memory. -Another advanced use-case includes a fine-tunable HTTP client, such as the one found at https://github.com/src-d/go-git/blob/master/_examples/custom_http/main.go[]. +Another advanced use-case includes a fine-tunable HTTP client, such as the one found at https://github.com/go-git/go-git/blob/master/_examples/custom_http/main.go[^]. [source, go] ------ +---- customClient := &http.Client{ - Transport: &http.Transport{ // accept any certificate (might be useful for testing) - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - Timeout: 15 * time.Second, // 15 second timeout - CheckRedirect: func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse // don't follow redirect - }, + Transport: &http.Transport{ // accept any certificate (might be useful for testing) + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + Timeout: 15 * time.Second, // 15 second timeout + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse // don't follow redirect + }, } // Override http(s) default protocol to use our custom client @@ -77,10 +75,9 @@ client.InstallProtocol("https", githttp.NewClient(customClient)) // Clone repository using the new client if the protocol is https:// r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{URL: url}) ------ - +---- ==== Further Reading A full treatment of go-git's capabilities is outside the scope of this book. -If you want more information on go-git, there's API documentation at https://godoc.org/gopkg.in/src-d/go-git.v4[], and a set of usage examples at https://github.com/src-d/go-git/tree/master/_examples[]. +If you want more information on go-git, there's API documentation at https://pkg.go.dev/github.com/go-git/go-git/v5[^], and a set of usage examples at https://github.com/go-git/go-git/tree/master/_examples[^]. diff --git a/book/B-embedding-git/sections/jgit.asc b/book/B-embedding-git/sections/jgit.asc index 010252118..74ae05a38 100644 --- a/book/B-embedding-git/sections/jgit.asc +++ b/book/B-embedding-git/sections/jgit.asc @@ -3,12 +3,12 @@ (((jgit)))(((Java))) If you want to use Git from within a Java program, there is a fully featured Git library called JGit. JGit is a relatively full-featured implementation of Git written natively in Java, and is widely used in the Java community. -The JGit project is under the Eclipse umbrella, and its home can be found at https://www.eclipse.org/jgit/[]. +The JGit project is under the Eclipse umbrella, and its home can be found at https://projects.eclipse.org/projects/technology.jgit[^]. ==== Getting Set Up There are a number of ways to connect your project with JGit and start writing code against it. -Probably the easiest is to use Maven – the integration is accomplished by adding the following snippet to the `` tag in your pom.xml file: +Probably the easiest is to use Maven – the integration is accomplished by adding the following snippet to the `` tag in your `pom.xml` file: [source,xml] ---- @@ -19,10 +19,10 @@ Probably the easiest is to use Maven – the integration is accomplished by addi ---- -The `version` will most likely have advanced by the time you read this; check https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit[] for updated repository information. +The `version` will most likely have advanced by the time you read this; check https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit[^] for updated repository information. Once this step is done, Maven will automatically acquire and use the JGit libraries that you'll need. -If you would rather manage the binary dependencies yourself, pre-built JGit binaries are available from https://www.eclipse.org/jgit/download[]. +If you would rather manage the binary dependencies yourself, pre-built JGit binaries are available from https://projects.eclipse.org/projects/technology.jgit/downloads[^]. You can build them into your project by running a command like this: [source,console] @@ -91,9 +91,9 @@ String name = cfg.getString("user", null, "name"); There's quite a bit going on here, so let's go through it one section at a time. The first line gets a pointer to the `master` reference. -JGit automatically grabs the _actual_ master ref, which lives at `refs/heads/master`, and returns an object that lets you fetch information about the reference. +JGit automatically grabs the _actual_ `master` ref, which lives at `refs/heads/master`, and returns an object that lets you fetch information about the reference. You can get the name (`.getName()`), and either the target object of a direct reference (`.getObjectId()`) or the reference pointed to by a symbolic ref (`.getTarget()`). -Ref objects are also used to represent tag refs and objects, so you can ask if the tag is ``peeled,'' meaning that it points to the final target of a (potentially long) string of tag objects. +Ref objects are also used to represent tag refs and objects, so you can ask if the tag is "`peeled,`" meaning that it points to the final target of a (potentially long) string of tag objects. The second line gets the target of the `master` reference, which is returned as an ObjectId instance. ObjectId represents the SHA-1 hash of an object, which might or might not exist in Git's object database. @@ -128,7 +128,7 @@ Git git = new Git(repo); ---- The Git class has a nice set of high-level _builder_-style methods that can be used to construct some pretty complex behavior. -Let's take a look at an example – doing something like `git ls-remote`: +Let's take a look at an example -- doing something like `git ls-remote`: [source,java] ---- @@ -155,6 +155,6 @@ Many other commands are available through the Git class, including but not limit This is only a small sampling of JGit's full capabilities. If you're interested and want to learn more, here's where to look for information and inspiration: -* The official JGit API documentation can be found at https://www.eclipse.org/jgit/documentation[]. +* The official JGit API documentation can be found at https://help.eclipse.org/latest/topic/org.eclipse.egit.doc/help/JGit/User_Guide/User-Guide.html[^]. These are standard Javadoc, so your favorite JVM IDE will be able to install them locally, as well. -* The JGit Cookbook at https://github.com/centic9/jgit-cookbook[] has many examples of how to do specific tasks with JGit. +* The JGit Cookbook at https://github.com/centic9/jgit-cookbook[^] has many examples of how to do specific tasks with JGit. diff --git a/book/B-embedding-git/sections/libgit2.asc b/book/B-embedding-git/sections/libgit2.asc index 1c2e95911..2e006fdc0 100644 --- a/book/B-embedding-git/sections/libgit2.asc +++ b/book/B-embedding-git/sections/libgit2.asc @@ -3,13 +3,13 @@ (((libgit2)))((("C"))) Another option at your disposal is to use Libgit2. Libgit2 is a dependency-free implementation of Git, with a focus on having a nice API for use within other programs. -You can find it at https://libgit2.org[]. +You can find it at https://libgit2.org[^]. First, let's take a look at what the C API looks like. Here's a whirlwind tour: [source,c] ------ +---- // Open a repository git_repository *repo; int error = git_repository_open(&repo, "/path/to/repository"); @@ -28,7 +28,7 @@ const git_oid *tree_id = git_commit_tree_id(commit); // Cleanup git_commit_free(commit); git_repository_free(repo); ------ +---- The first couple of lines open a Git repository. The `git_repository` type represents a handle to a repository with a cache in memory. @@ -37,7 +37,7 @@ There's also the `git_repository_open_ext` which includes options for searching, The second chunk of code uses rev-parse syntax (see <> for more on this) to get the commit that HEAD eventually points to. The type returned is a `git_object` pointer, which represents something that exists in the Git object database for a repository. -`git_object` is actually a ``parent'' type for several different kinds of objects; the memory layout for each of the ``child'' types is the same as for `git_object`, so you can safely cast to the right one. +`git_object` is actually a "`parent`" type for several different kinds of objects; the memory layout for each of the "`child`" types is the same as for `git_object`, so you can safely cast to the right one. In this case, `git_object_type(commit)` would return `GIT_OBJ_COMMIT`, so it's safe to cast to a `git_commit` pointer. The next chunk shows how to access the commit's properties. @@ -54,7 +54,7 @@ From this sample, a couple of patterns have started to emerge: (((Ruby))) That last one means it isn't very probable that you'll be writing C when using Libgit2. Fortunately, there are a number of language-specific bindings available that make it fairly easy to work with Git repositories from your specific language and environment. -Let's take a look at the above example written using the Ruby bindings for Libgit2, which are named Rugged, and can be found at https://github.com/libgit2/rugged[]. +Let's take a look at the above example written using the Ruby bindings for Libgit2, which are named Rugged, and can be found at https://github.com/libgit2/rugged[^]. [source,ruby] ---- @@ -66,7 +66,7 @@ tree = commit.tree ---- As you can see, the code is much less cluttered. -Firstly, Rugged uses exceptions; it can raise things like `ConfigError` or `ObjectError` to signal error conditions. +Firstly, Rugged uses exceptions; it can raise things like `ConfigError` or `ObjectError` to signal error conditions. Secondly, there's no explicit freeing of resources, since Ruby is garbage-collected. Let's take a look at a slightly more complicated example: crafting a commit from scratch @@ -108,15 +108,14 @@ commit = repo.lookup(commit_id) # <8> The Ruby code is nice and clean, but since Libgit2 is doing the heavy lifting, this code will run pretty fast, too. If you're not a rubyist, we touch on some other bindings in <<_libgit2_bindings>>. - ==== Advanced Functionality Libgit2 has a couple of capabilities that are outside the scope of core Git. -One example is pluggability: Libgit2 allows you to provide custom ``backends'' for several types of operation, so you can store things in a different way than stock Git does. +One example is pluggability: Libgit2 allows you to provide custom "`backends`" for several types of operation, so you can store things in a different way than stock Git does. Libgit2 allows custom backends for configuration, ref storage, and the object database, among other things. Let's take a look at how this works. -The code below is borrowed from the set of backend examples provided by the Libgit2 team (which can be found at https://github.com/libgit2/libgit2-backends[]). +The code below is borrowed from the set of backend examples provided by the Libgit2 team (which can be found at https://github.com/libgit2/libgit2-backends[^]). Here's how a custom backend for the object database is set up: [source,c] @@ -131,12 +130,12 @@ error = git_odb_add_backend(odb, my_backend, 1); // <3> git_repository *repo; error = git_repository_open(&repo, "some-path"); -error = git_repository_set_odb(odb); // <4> +error = git_repository_set_odb(repo, odb); // <4> ---- -_(Note that errors are captured, but not handled. We hope your code is better than ours.)_ +_Note that errors are captured, but not handled. We hope your code is better than ours._ -<1> Initialize an empty object database (ODB) ``frontend,'' which will act as a container for the ``backends'' which are the ones doing the real work. +<1> Initialize an empty object database (ODB) "`frontend,`" which will act as a container for the "`backends`" which are the ones doing the real work. <2> Initialize a custom ODB backend. <3> Add the backend to the frontend. <4> Open a repository, and set it to use our ODB to look up objects. @@ -173,7 +172,7 @@ int git_odb_backend_mine(git_odb_backend **backend_out, /*…*/) } ---- -The subtlest constraint here is that `my_backend_struct`'s first member must be a `git_odb_backend` structure; this ensures that the memory layout is what the Libgit2 code expects it to be. +The subtlest constraint here is that ``my_backend_struct```'s first member must be a ``git_odb_backend`` structure; this ensures that the memory layout is what the Libgit2 code expects it to be. The rest of it is arbitrary; this structure can be as large or small as you need it to be. The initialization function allocates some memory for the structure, sets up the custom context, and then fills in the members of the `parent` structure that it supports. @@ -184,21 +183,20 @@ Take a look at the `include/git2/sys/odb_backend.h` file in the Libgit2 source f Libgit2 has bindings for many languages. Here we show a small example using a few of the more complete bindings packages as of this writing; libraries exist for many other languages, including C++, Go, Node.js, Erlang, and the JVM, all in various stages of maturity. -The official collection of bindings can be found by browsing the repositories at https://github.com/libgit2[]. +The official collection of bindings can be found by browsing the repositories at https://github.com/libgit2[^]. The code we'll write will return the commit message from the commit eventually pointed to by HEAD (sort of like `git log -1`). - ===== LibGit2Sharp (((.NET)))(((C#)))(((Mono))) -If you're writing a .NET or Mono application, LibGit2Sharp (https://github.com/libgit2/libgit2sharp[]) is what you're looking for. +If you're writing a .NET or Mono application, LibGit2Sharp (https://github.com/libgit2/libgit2sharp[^]) is what you're looking for. The bindings are written in C#, and great care has been taken to wrap the raw Libgit2 calls with native-feeling CLR APIs. Here's what our example program looks like: [source,csharp] ------ +---- new Repository(@"C:\path\to\repo").Head.Tip.Message; ------ +---- For desktop Windows applications, there's even a NuGet package that will help you get started quickly. @@ -206,23 +204,22 @@ For desktop Windows applications, there's even a NuGet package that will help yo (((Apple)))(((Objective-C)))(((Cocoa))) If your application is running on an Apple platform, you're likely using Objective-C as your implementation language. -Objective-Git (https://github.com/libgit2/objective-git[]) is the name of the Libgit2 bindings for that environment. +Objective-Git (https://github.com/libgit2/objective-git[^]) is the name of the Libgit2 bindings for that environment. The example program looks like this: [source,objc] ------ +---- GTRepository *repo = [[GTRepository alloc] initWithURL:[NSURL fileURLWithPath: @"/path/to/repo"] error:NULL]; NSString *msg = [[[repo headReferenceWithError:NULL] resolvedTarget] message]; ------ +---- Objective-git is fully interoperable with Swift, so don't fear if you've left Objective-C behind. - ===== pygit2 (((Python))) -The bindings for Libgit2 in Python are called Pygit2, and can be found at https://www.pygit2.org[]. +The bindings for Libgit2 in Python are called Pygit2, and can be found at https://www.pygit2.org[^]. Our example program: [source,python] @@ -233,9 +230,8 @@ pygit2.Repository("/path/to/repo") # open repository .message # read the message ---- - ==== Further Reading Of course, a full treatment of Libgit2's capabilities is outside the scope of this book. -If you want more information on Libgit2 itself, there's API documentation at https://libgit2.github.com/libgit2[], and a set of guides at https://libgit2.github.com/docs[]. +If you want more information on Libgit2 itself, there's API documentation at https://libgit2.github.com/libgit2[^], and a set of guides at https://libgit2.github.com/docs[^]. For the other bindings, check the bundled README and tests; there are often small tutorials and pointers to further reading there. diff --git a/book/contributors.asc b/book/contributors.asc index 8bfa48a71..32acb1e05 100644 --- a/book/contributors.asc +++ b/book/contributors.asc @@ -9,4 +9,3 @@ Thank you everyone for helping make this a better book for everyone. ---- include::contributors.txt[] ---- - diff --git a/book/dedication.asc b/book/dedication.asc index d7d826b8c..0c75ccb4b 100644 --- a/book/dedication.asc +++ b/book/dedication.asc @@ -4,5 +4,4 @@ _To my wife, Becky, without whom this adventure never would have begun. — Ben_ _This edition is dedicated to my girls. -To my wife Jessica who has supported me for all of these years and to my daughter Josephine, -who will support me when I'm too old to know what's going on. — Scott_ +To my wife Jessica who has supported me for all of these years and to my daughter Josephine, who will support me when I'm too old to know what's going on. — Scott_ diff --git a/book/index.asc b/book/index.asc deleted file mode 100644 index 9b0c1cfae..000000000 --- a/book/index.asc +++ /dev/null @@ -1 +0,0 @@ -== Index diff --git a/book/introduction.asc b/book/introduction.asc index b2981600e..23b261dce 100644 --- a/book/introduction.asc +++ b/book/introduction.asc @@ -40,8 +40,7 @@ A lot of organizations still use SVN and are not about to change, but by this po We also cover how to import projects from several different systems in case you do convince everyone to make the plunge. *Chapter 10* delves into the murky yet beautiful depths of Git internals. -Now that you know all about Git and can wield it with power and grace, you can move on to discuss how Git stores its objects, -what the object model is, details of packfiles, server protocols, and more. +Now that you know all about Git and can wield it with power and grace, you can move on to discuss how Git stores its objects, what the object model is, details of packfiles, server protocols, and more. Throughout the book, we will refer to sections of this chapter in case you feel like diving deep at that point; but if you are like us and want to dive into the technical details, you may want to read Chapter 10 first. We leave that up to you. diff --git a/book/license.asc b/book/license.asc index 490603e1f..090996abc 100644 --- a/book/license.asc +++ b/book/license.asc @@ -1,4 +1,4 @@ [preface] -== Licence +== License include::../LICENSE.asc[] diff --git a/book/preface_schacon.asc b/book/preface_schacon.asc index 29d78e5e7..bf31c08ca 100644 --- a/book/preface_schacon.asc +++ b/book/preface_schacon.asc @@ -33,4 +33,3 @@ It's been amazing to watch Git grow over the past few years from a relatively ob I'm happy that Pro Git has done so well and has also been able to be one of the few technical books on the market that is both quite successful and fully open source. I hope you enjoy this updated edition of Pro Git. - diff --git a/callouts/1.pdf b/callouts/1.pdf old mode 100755 new mode 100644 diff --git a/callouts/10.pdf b/callouts/10.pdf old mode 100755 new mode 100644 diff --git a/callouts/2.pdf b/callouts/2.pdf old mode 100755 new mode 100644 diff --git a/callouts/3.pdf b/callouts/3.pdf old mode 100755 new mode 100644 diff --git a/callouts/4.pdf b/callouts/4.pdf old mode 100755 new mode 100644 diff --git a/callouts/5.pdf b/callouts/5.pdf old mode 100755 new mode 100644 diff --git a/callouts/6.pdf b/callouts/6.pdf old mode 100755 new mode 100644 diff --git a/callouts/7.pdf b/callouts/7.pdf old mode 100755 new mode 100644 diff --git a/callouts/8.pdf b/callouts/8.pdf old mode 100755 new mode 100644 diff --git a/callouts/9.pdf b/callouts/9.pdf old mode 100755 new mode 100644 diff --git a/ch03-git-branching.asc b/ch03-git-branching.asc index d1528f224..60d1a1934 100644 --- a/ch03-git-branching.asc +++ b/ch03-git-branching.asc @@ -6,7 +6,7 @@ Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects. -Some people refer to Git's branching model as its ``killer feature,'' and it certainly sets Git apart in the VCS community. +Some people refer to Git's branching model as its "`killer feature,`" and it certainly sets Git apart in the VCS community. Why is it so special? The way Git branches is incredibly lightweight, making branching operations nearly instantaneous, and switching back and forth between branches generally just as fast. Unlike many other VCSs, Git encourages workflows that branch and merge often, even multiple times in a day. diff --git a/ch09-git-and-other-systems.asc b/ch09-git-and-other-systems.asc index 43b0b3590..af4f22008 100644 --- a/ch09-git-and-other-systems.asc +++ b/ch09-git-and-other-systems.asc @@ -13,19 +13,15 @@ The second part of this chapter covers how to migrate your project into Git from (((Git as a client))) Git provides such a nice experience for developers that many people have figured out how to use it on their workstation, even if the rest of their team is using an entirely different VCS. -There are a number of these adapters, called ``bridges,'' available. +There are a number of these adapters, called "`bridges,`" available. Here we'll cover the ones you're most likely to run into in the wild. include::book/09-git-and-other-scms/sections/client-svn.asc[] include::book/09-git-and-other-scms/sections/client-hg.asc[] -include::book/09-git-and-other-scms/sections/client-bzr.asc[] - include::book/09-git-and-other-scms/sections/client-p4.asc[] -include::book/09-git-and-other-scms/sections/client-tfs.asc[] - [[_migrating]] === Migrating to Git @@ -38,12 +34,8 @@ include::book/09-git-and-other-scms/sections/import-svn.asc[] include::book/09-git-and-other-scms/sections/import-hg.asc[] -include::book/09-git-and-other-scms/sections/import-bzr.asc[] - include::book/09-git-and-other-scms/sections/import-p4.asc[] -include::book/09-git-and-other-scms/sections/import-tfs.asc[] - include::book/09-git-and-other-scms/sections/import-custom.asc[] === Summary diff --git a/diagram-source/progit.sketch b/diagram-source/progit.sketch index 9b804c75c..51603807a 100644 Binary files a/diagram-source/progit.sketch and b/diagram-source/progit.sketch differ diff --git a/images/2fa-1.png b/images/2fa-1.png index 5abd7437a..02725b9e9 100644 Binary files a/images/2fa-1.png and b/images/2fa-1.png differ diff --git a/images/advance-master.png b/images/advance-master.png index c3a7ebe6b..44aa8de68 100644 Binary files a/images/advance-master.png and b/images/advance-master.png differ diff --git a/images/advance-master.svg b/images/advance-master.svg new file mode 100644 index 000000000..4fede8f41 --- /dev/null +++ b/images/advance-master.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + images/advance-master + + + + images/advance-master + Created with Sketch. + + + + + + + + + + f30ab + + + + 34ac2 + + + + 98ca9 + + + + 87ab2 + + + + c2b9e + + + + + + + testing + + + + + + + master + + + + + HEAD + + + diff --git a/images/advance-testing.png b/images/advance-testing.png index 312e65e15..82e07c092 100644 Binary files a/images/advance-testing.png and b/images/advance-testing.png differ diff --git a/images/advance-testing.svg b/images/advance-testing.svg new file mode 100644 index 000000000..2a061b127 --- /dev/null +++ b/images/advance-testing.svg @@ -0,0 +1,52 @@ + + + + + + image/svg+xml + + images/advance-testing + + + + images/advance-testing + Created with Sketch. + + + + + + + + + master + + + + + f30ab + + + + 87ab2 + + + + 34ac2 + + + + 98ca9 + + + + + + testing + + + + + HEAD + + diff --git a/images/areas.png b/images/areas.png index da98fb034..94b77a1ee 100644 Binary files a/images/areas.png and b/images/areas.png differ diff --git a/images/areas.svg b/images/areas.svg new file mode 100644 index 000000000..c7840b109 --- /dev/null +++ b/images/areas.svg @@ -0,0 +1,53 @@ + + + + + + image/svg+xml + + images/areas + + + + images/areas + Created with Sketch. + + + + + + + + + + + + StagingArea + + + + + .git directory(Repository) + + + + Checkout the project + + + + Stage Fixes + + + + Commit + + + + + + WorkingTree + + + + + diff --git a/images/basic-branching-1.png b/images/basic-branching-1.png index acc3866f2..c6c6a38b6 100644 Binary files a/images/basic-branching-1.png and b/images/basic-branching-1.png differ diff --git a/images/basic-branching-1.svg b/images/basic-branching-1.svg new file mode 100644 index 000000000..d977cfbf6 --- /dev/null +++ b/images/basic-branching-1.svg @@ -0,0 +1,36 @@ + + + + + + image/svg+xml + + images/basic-branching-1 + + + + + images/basic-branching-1 + Created with Sketch. + + + C0 + + + + + + C1 + + + + C2 + + + + + + master + + + diff --git a/images/basic-branching-2.png b/images/basic-branching-2.png index c3f149141..8b7ff3c4c 100644 Binary files a/images/basic-branching-2.png and b/images/basic-branching-2.png differ diff --git a/images/basic-branching-2.svg b/images/basic-branching-2.svg new file mode 100644 index 000000000..6de510571 --- /dev/null +++ b/images/basic-branching-2.svg @@ -0,0 +1,41 @@ + + + + + + image/svg+xml + + images/basic-branching-2 + + + + + images/basic-branching-2 + Created with Sketch. + + + + C0 + + + + + + + + C1 + + + + C2 + + + + master + + + + iss53 + + + diff --git a/images/basic-branching-3.png b/images/basic-branching-3.png index ebc9ca95c..f4df8ce44 100644 Binary files a/images/basic-branching-3.png and b/images/basic-branching-3.png differ diff --git a/images/basic-branching-3.svg b/images/basic-branching-3.svg new file mode 100644 index 000000000..0192c1b4b --- /dev/null +++ b/images/basic-branching-3.svg @@ -0,0 +1,50 @@ + + + + + + image/svg+xml + + images/basic-branching-3 + + + + + images/basic-branching-3 + Created with Sketch. + + + + + + + + + C0 + + + + C1 + + + + C2 + + + + C3 + + + + + master + + + + + + iss53 + + + + diff --git a/images/basic-branching-4.png b/images/basic-branching-4.png index ab8f22283..e81d5636a 100644 Binary files a/images/basic-branching-4.png and b/images/basic-branching-4.png differ diff --git a/images/basic-branching-4.svg b/images/basic-branching-4.svg new file mode 100644 index 000000000..59691bd24 --- /dev/null +++ b/images/basic-branching-4.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/basic-branching-4 + + + + + images/basic-branching-4 + Created with Sketch. + + + + + + + + + + C0 + + + + C1 + + + + C2 + + + + + master + + + + + + + hotfix + + + + + C4 + + + + C3 + + + + + iss53 + + + + + + diff --git a/images/basic-branching-5.png b/images/basic-branching-5.png index 947133f77..269dbdd11 100644 Binary files a/images/basic-branching-5.png and b/images/basic-branching-5.png differ diff --git a/images/basic-branching-5.svg b/images/basic-branching-5.svg new file mode 100644 index 000000000..d3d8e87d8 --- /dev/null +++ b/images/basic-branching-5.svg @@ -0,0 +1,62 @@ + + + + + + image/svg+xml + + images/basic-branching-5 + + + + + images/basic-branching-5 + Created with Sketch. + + + + + + + C0 + + + + C1 + + + + C2 + + + + + master + + + + + + + hotfix + + + + + C4 + + + + + C3 + + + + + + + iss53 + + + + diff --git a/images/basic-branching-6.png b/images/basic-branching-6.png index 6023d6942..1e5a1c0c4 100644 Binary files a/images/basic-branching-6.png and b/images/basic-branching-6.png differ diff --git a/images/basic-branching-6.svg b/images/basic-branching-6.svg new file mode 100644 index 000000000..feaf578a5 --- /dev/null +++ b/images/basic-branching-6.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + images/basic-branching-6 + + + + + images/basic-branching-6 + Created with Sketch. + + + + + C0 + + + + C1 + + + + C2 + + + + + + + + + + + + master + + + + + C4 + + + + + + C5 + + + + + C3 + + + + + + iss53 + + + + + diff --git a/images/basic-merging-1.png b/images/basic-merging-1.png index e1bcc27f6..82a7148e4 100644 Binary files a/images/basic-merging-1.png and b/images/basic-merging-1.png differ diff --git a/images/basic-merging-1.svg b/images/basic-merging-1.svg new file mode 100644 index 000000000..012bc1d4f --- /dev/null +++ b/images/basic-merging-1.svg @@ -0,0 +1,63 @@ + + + + + + image/svg+xml + + images/basic-merging-1 + + + + + images/basic-merging-1 + Created with Sketch. + + + + + + + + C0 + + + + C1 + + + + C2 + + + + + + master + + Snapshot toMerge Into + + + C4 + + + + + C5 + + + + C3 + + + + + + iss53 + + + Common Ancestor + Snapshot toMerge In + + + diff --git a/images/basic-merging-2.png b/images/basic-merging-2.png index a24382666..d60f46620 100644 Binary files a/images/basic-merging-2.png and b/images/basic-merging-2.png differ diff --git a/images/basic-merging-2.svg b/images/basic-merging-2.svg new file mode 100644 index 000000000..856d14357 --- /dev/null +++ b/images/basic-merging-2.svg @@ -0,0 +1,68 @@ + + + + + + image/svg+xml + + images/basic-merging-2 + + + + + images/basic-merging-2 + Created with Sketch. + + + + + + + C0 + + + + C1 + + + + C2 + + + + + + + master + + + + + C4 + + + + + + C5 + + + + + + + C6 + + + + C3 + + + + + + iss53 + + + + diff --git a/images/basic-rebase-1.png b/images/basic-rebase-1.png index 44ea49e3e..e9494b0f7 100644 Binary files a/images/basic-rebase-1.png and b/images/basic-rebase-1.png differ diff --git a/images/basic-rebase-1.svg b/images/basic-rebase-1.svg new file mode 100644 index 000000000..111bbf0d6 --- /dev/null +++ b/images/basic-rebase-1.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + images/basic-rebase-1 + + + + + images/basic-rebase-1 + Created with Sketch. + + + + + + + C0 + + + + C1 + + + + C2 + + + + + + + experiment + + + + + + C4 + + + + C3 + + + + + + + master + + + + diff --git a/images/basic-rebase-2.png b/images/basic-rebase-2.png index c82140cdd..efb9bc4cb 100644 Binary files a/images/basic-rebase-2.png and b/images/basic-rebase-2.png differ diff --git a/images/basic-rebase-2.svg b/images/basic-rebase-2.svg new file mode 100644 index 000000000..6c1085198 --- /dev/null +++ b/images/basic-rebase-2.svg @@ -0,0 +1,63 @@ + + + + + + image/svg+xml + + images/basic-rebase-2 + + + + + images/basic-rebase-2 + Created with Sketch. + + + + + + C0 + + + + C1 + + + + C2 + + + + + + + + experiment + + + + + C4 + + + + + + C3 + + + + + + C5 + + + + + + master + + + + diff --git a/images/basic-rebase-3.png b/images/basic-rebase-3.png index a1afaef66..846aebccb 100644 Binary files a/images/basic-rebase-3.png and b/images/basic-rebase-3.png differ diff --git a/images/basic-rebase-3.svg b/images/basic-rebase-3.svg new file mode 100644 index 000000000..9bb11f9ab --- /dev/null +++ b/images/basic-rebase-3.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/basic-rebase-3 + + + + + images/basic-rebase-3 + Created with Sketch. + + + + + + C0 + + + + C1 + + + + C2 + + + + + + experiment + + + + + + + C4 + + + + + + + C3 + + + + + + C4' + + + + + + master + + + + diff --git a/images/basic-rebase-4.png b/images/basic-rebase-4.png index e97c1685f..ea75fce34 100644 Binary files a/images/basic-rebase-4.png and b/images/basic-rebase-4.png differ diff --git a/images/basic-rebase-4.svg b/images/basic-rebase-4.svg new file mode 100644 index 000000000..f7ce55ae0 --- /dev/null +++ b/images/basic-rebase-4.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + images/basic-rebase-4 + + + + + images/basic-rebase-4 + Created with Sketch. + + + + + + C0 + + + + C1 + + + + C2 + + + + + + experiment + + + + + + + C3 + + + + + + C4' + + + + + + master + + + + diff --git a/images/benevolent-dictator.png b/images/benevolent-dictator.png index aeb47e7cf..3f89db8ad 100644 Binary files a/images/benevolent-dictator.png and b/images/benevolent-dictator.png differ diff --git a/images/benevolent-dictator.svg b/images/benevolent-dictator.svg new file mode 100644 index 000000000..a70712c19 --- /dev/null +++ b/images/benevolent-dictator.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/benevolent-dictator + + + + + images/benevolent-dictator + Created with Sketch. + + + + + + + + lieutenant + + + + + + + lieutenant + + + + + + developerpublic + + + + + + + + + + + dictator + + + + developerpublic + + + + developerpublic + + + + + + blessedrepository + + + + diff --git a/images/bitnami.png b/images/bitnami.png deleted file mode 100644 index 9852e7276..000000000 Binary files a/images/bitnami.png and /dev/null differ diff --git a/images/branch-and-history.png b/images/branch-and-history.png index 2b4ab17e6..71bd27c08 100644 Binary files a/images/branch-and-history.png and b/images/branch-and-history.png differ diff --git a/images/branch-and-history.svg b/images/branch-and-history.svg new file mode 100644 index 000000000..2996565e1 --- /dev/null +++ b/images/branch-and-history.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + images/branch-and-history + + + + + images/branch-and-history + Created with Sketch. + + + + + Snapshot C + + + + + Snapshot B + + + + + Snapshot A + + + + f30ab + + + + + + + 34ac2 + + + + 98ca9 + + + + + + master + + + + HEAD + + + + v1.0 + + + diff --git a/images/centralized.png b/images/centralized.png index 9aa3e902c..4cdaca133 100644 Binary files a/images/centralized.png and b/images/centralized.png differ diff --git a/images/centralized.svg b/images/centralized.svg new file mode 100644 index 000000000..b5583f1c7 --- /dev/null +++ b/images/centralized.svg @@ -0,0 +1,39 @@ + + + + + + image/svg+xml + + images/centralized + + + + images/centralized + Created with Sketch. + + + + + developer + + + + developer + + + + developer + + + + + + + + sharedrepository + + + + + diff --git a/images/checkout-master.png b/images/checkout-master.png index 06e98787c..a133f42a9 100644 Binary files a/images/checkout-master.png and b/images/checkout-master.png differ diff --git a/images/checkout-master.svg b/images/checkout-master.svg new file mode 100644 index 000000000..04a1a20af --- /dev/null +++ b/images/checkout-master.svg @@ -0,0 +1,53 @@ + + + + + + image/svg+xml + + images/checkout-master + + + + + images/checkout-master + Created with Sketch. + + + + + + + + + master + + + + f30ab + + + + 87ab2 + + + + 34ac2 + + + + 98ca9 + + + + + testing + + + + + HEAD + + + + diff --git a/images/clean.png b/images/clean.png index ec8fcaa52..677a8c5b5 100644 Binary files a/images/clean.png and b/images/clean.png differ diff --git a/images/clean.svg b/images/clean.svg new file mode 100644 index 000000000..7683b3306 --- /dev/null +++ b/images/clean.svg @@ -0,0 +1,282 @@ + + + + + + + image/svg+xml + + images/clean + + + + + images/clean + Created with Sketch. + + + + + + + fileA.txt + + + + + + + fileA.txt' + + + + + + fileB.txt' + + + + + + fileB.txt + + + + + + fileC.rb + + + + + + fileC.rb + + + + Staging Area + + + Working Directory + + + *.txt Filter + + + + + smudge + + + + + + clean + + + + + + + + + + + diff --git a/images/commit-and-tree.png b/images/commit-and-tree.png index 3ddf1cd5f..e840e891b 100644 Binary files a/images/commit-and-tree.png and b/images/commit-and-tree.png differ diff --git a/images/commit-and-tree.svg b/images/commit-and-tree.svg new file mode 100644 index 000000000..3c3112b8d --- /dev/null +++ b/images/commit-and-tree.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + images/commit-and-tree + + + + + images/commit-and-tree + Created with Sketch. + + + + + size 5b1d3 README 911e7 LICENSE cba0a test.rb + treeblobblobblob + + + + The initial commit of my project + + size 92ec2 Scott Scott + committreeauthorcommitter + + 98ca9 + + 92ec2 + + + size + blob + == Testing library This library is used to test Ruby projects. + 5b1d3 + + + + size + blob + The MIT License Copyright (c) 2008 Scott Chacon Permission is hereby granted, free of charge, to any person + 911e7 + + + + size + blob + require 'logger' require 'test/unit' class Test::Unit::TestCase + cba0a + + + + + + + + + + diff --git a/images/commits-and-parents.png b/images/commits-and-parents.png index d56397266..399b2d008 100644 Binary files a/images/commits-and-parents.png and b/images/commits-and-parents.png differ diff --git a/images/commits-and-parents.svg b/images/commits-and-parents.svg new file mode 100644 index 000000000..ee786daa3 --- /dev/null +++ b/images/commits-and-parents.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + images/commits-and-parents + + + + + images/commits-and-parents + Created with Sketch. + + + Snapshot A + + + + Snapshot B + + + 98ca9 + 34ac2 + + + + Snapshot C + + + f30ab + + + + Fixed bug #1328 - stack overflow under certain conditions + + size 184ca 98ca9 Scott Scott + committreeparentauthorcommitter + + + + + The initial commit of my project + + size 92ec2 Scott Scott + committreeparentauthorcommitter + + + + + add feature #32 - ability to add new formats to the central interface + + size 0de24 34ac2 Scott Scott + committreeparentauthorcommitter + + + + diff --git a/images/data-model-1.png b/images/data-model-1.png index 9331e9152..410ff7db4 100644 Binary files a/images/data-model-1.png and b/images/data-model-1.png differ diff --git a/images/data-model-1.svg b/images/data-model-1.svg new file mode 100644 index 000000000..5888cbe3e --- /dev/null +++ b/images/data-model-1.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + images/data-model-1 + + + + + images/data-model-1 + Created with Sketch. + + + + blob + + + + blob + + + + blob + + + + + + + + simplegit.rb + + + + Rakefile + + + + README + + + + lib + + + + tree + + + + tree + + + diff --git a/images/data-model-2.png b/images/data-model-2.png index eb1d48e15..1d7487276 100644 Binary files a/images/data-model-2.png and b/images/data-model-2.png differ diff --git a/images/data-model-2.svg b/images/data-model-2.svg new file mode 100644 index 000000000..a675500e6 --- /dev/null +++ b/images/data-model-2.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + images/data-model-2 + + + + + images/data-model-2 + Created with Sketch. + + + + + "version 2" + 1f7a7a + + + + "new file" + fa49b0 + + + + "version 1" + 83baae + + + + + + + + test.txt + + + + test.txt + + + + new.txt + + + + bak + + + + + tree + 3c4e9c + + + + + tree + d8329f + + + + diff --git a/images/data-model-3.png b/images/data-model-3.png index 317acbb07..5aa0edef1 100644 Binary files a/images/data-model-3.png and b/images/data-model-3.png differ diff --git a/images/data-model-3.svg b/images/data-model-3.svg new file mode 100644 index 000000000..0f03b451a --- /dev/null +++ b/images/data-model-3.svg @@ -0,0 +1,97 @@ + + + + + + image/svg+xml + + images/data-model-3 + + + + + images/data-model-3 + Created with Sketch. + + + + + + + + + + + + + "version 2" + 1f7a7a + + + + "new file" + fa49b0 + + + + "version 1" + 83baae + + + + test.txt + + + + test.txt + + + + test.txt + + + + new.txt + + + + new.txt + + + + bak + + + + tree + 3c4e9c + + + + third commit + 1a410e + + + + + second commit + cac0ca + + + + + first commit + fdf4fc + + + + tree + 0155eb + + + + tree + d8329f + + + diff --git a/images/data-model-4.png b/images/data-model-4.png index 381364402..98cc08a10 100644 Binary files a/images/data-model-4.png and b/images/data-model-4.png differ diff --git a/images/data-model-4.svg b/images/data-model-4.svg new file mode 100644 index 000000000..05b8bd8bd --- /dev/null +++ b/images/data-model-4.svg @@ -0,0 +1,111 @@ + + + + + + image/svg+xml + + images/data-model-4 + + + + + images/data-model-4 + Created with Sketch. + + + + + + + + + + + + + "version 2" + 1f7a7a + + + + "new file" + fa49b0 + + + + "version 1" + 83baae + + + + test.txt + + + + test.txt + + + + test.txt + + + + new.txt + + + + new.txt + + + + bak + + + + tree + 3c4e9c + + + + third commit + 1a410e + + + + + second commit + cac0ca + + + + + first commit + fdf4fc + + + + + + refs/heads/test + + + + + + + refs/heads/master + + + + + tree + 0155eb + + + + tree + d8329f + + + diff --git a/images/deltas.png b/images/deltas.png index 47904edb0..0ea5684c9 100644 Binary files a/images/deltas.png and b/images/deltas.png differ diff --git a/images/deltas.svg b/images/deltas.svg new file mode 100644 index 000000000..9dc3a541c --- /dev/null +++ b/images/deltas.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + images/deltas + + + + images/deltas + Created with Sketch. + + + Version 1 + + Version 2 + + Version 3 + + Version 4 + + Version 5 + + + File A + + + File A + + Δ1 + + Δ1 + + Δ2 + + Δ1 + + Δ2 + + Δ2 + + Δ3 + + File B + + File C + + + + + + + + + + + + Checkins Over Time + diff --git a/images/distributed.png b/images/distributed.png index 53cfcaebc..834667437 100644 Binary files a/images/distributed.png and b/images/distributed.png differ diff --git a/images/distributed.svg b/images/distributed.svg new file mode 100644 index 000000000..072dc4702 --- /dev/null +++ b/images/distributed.svg @@ -0,0 +1,99 @@ + + + + + + image/svg+xml + + images/distributed + + + + images/distributed + Created with Sketch. + + + + Version Database + + + + + Version 3 + + + + Version 2 + + + + Version 1 + + + + + + Server Computer + + + Version Database + + + + + Version 3 + + + + Version 2 + + + + Version 1 + + + + + + + Computer A + + + File + + + + + + Version Database + + + + + Version 3 + + + + Version 2 + + + + Version 1 + + + + + + + Computer B + + + File + + + + + + + + diff --git a/images/double-dot.png b/images/double-dot.png index 53175c15d..0f50ff5b9 100644 Binary files a/images/double-dot.png and b/images/double-dot.png differ diff --git a/images/double-dot.svg b/images/double-dot.svg new file mode 100644 index 000000000..465b050e8 --- /dev/null +++ b/images/double-dot.svg @@ -0,0 +1,330 @@ + + + + + + image/svg+xml + + images/double-dot + + + + + + + + + images/double-dot + Created with Sketch. + + + + + A + + + + + + + + B + + + + + + + + + E + + + + + + + + + + F + + + + + + + + + C + + + + + + + + + D + + + + + + + + + master + + + + + + + + + experiment + + + + + diff --git a/images/egit.png b/images/egit.png deleted file mode 100644 index 27a7011a0..000000000 Binary files a/images/egit.png and /dev/null differ diff --git a/images/git-tfs-ct.png b/images/git-tfs-ct.png deleted file mode 100644 index d081f2723..000000000 Binary files a/images/git-tfs-ct.png and /dev/null differ diff --git a/images/head-to-master.png b/images/head-to-master.png index 86c7ae858..cc6a65b9f 100644 Binary files a/images/head-to-master.png and b/images/head-to-master.png differ diff --git a/images/head-to-master.svg b/images/head-to-master.svg new file mode 100644 index 000000000..285833a83 --- /dev/null +++ b/images/head-to-master.svg @@ -0,0 +1,46 @@ + + + + + + image/svg+xml + + images/head-to-master + + + + + images/head-to-master + Created with Sketch. + + + + + + + + + master + + + + testing + + + + f30ab + + + + 34ac2 + + + + 98ca9 + + + + HEAD + + + diff --git a/images/head-to-testing.png b/images/head-to-testing.png index 08352d608..6b329fdd2 100644 Binary files a/images/head-to-testing.png and b/images/head-to-testing.png differ diff --git a/images/head-to-testing.svg b/images/head-to-testing.svg new file mode 100644 index 000000000..0ea2c506a --- /dev/null +++ b/images/head-to-testing.svg @@ -0,0 +1,46 @@ + + + + + + image/svg+xml + + images/head-to-testing + + + + + images/head-to-testing + Created with Sketch. + + + + + + + + master + + + + testing + + + + f30ab + + + + 34ac2 + + + + 98ca9 + + + + + HEAD + + + diff --git a/images/integration-manager.png b/images/integration-manager.png index fd0d531eb..d5432179a 100644 Binary files a/images/integration-manager.png and b/images/integration-manager.png differ diff --git a/images/integration-manager.svg b/images/integration-manager.svg new file mode 100644 index 000000000..2661c070f --- /dev/null +++ b/images/integration-manager.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + images/integration-manager + + + + + images/integration-manager + Created with Sketch. + + + + + + developer public + + + + developer private + + + + + + + + + + + + + blessedrepository + + + + integrationmanager + + + + developerpublic + + + + developerpublic + + developerprivate + developerprivate + + + + diff --git a/images/interesting-rebase-1.png b/images/interesting-rebase-1.png index ed58a06c0..ac53ee0c4 100644 Binary files a/images/interesting-rebase-1.png and b/images/interesting-rebase-1.png differ diff --git a/images/interesting-rebase-1.svg b/images/interesting-rebase-1.svg new file mode 100644 index 000000000..5c520bf9b --- /dev/null +++ b/images/interesting-rebase-1.svg @@ -0,0 +1,98 @@ + + + + + + image/svg+xml + + images/interesting-rebase-1 + + + + + images/interesting-rebase-1 + Created with Sketch. + + + + C1 + + + + + + C2 + + + + + + + C5 + + + + + + + master + + + + + + + C6 + + + + + + + C3 + + + + + + + C4 + + + + + + + + + C8 + + + + + + + C9 + + + + + + + C10 + + + + + + + server + + + + + + client + + + diff --git a/images/interesting-rebase-2.png b/images/interesting-rebase-2.png index 95c306810..4984b8988 100644 Binary files a/images/interesting-rebase-2.png and b/images/interesting-rebase-2.png differ diff --git a/images/interesting-rebase-2.svg b/images/interesting-rebase-2.svg new file mode 100644 index 000000000..fb5feecb5 --- /dev/null +++ b/images/interesting-rebase-2.svg @@ -0,0 +1,110 @@ + + + + + + image/svg+xml + + images/interesting-rebase-2 + + + + + images/interesting-rebase-2 + Created with Sketch. + + + + C1 + + + + + + C2 + + + + + + + C5 + + + + + + + master + + + + + + + C6 + + + + + + + C8' + + + + + + + C9' + + + + + + + C3 + + + + + + + C4 + + + + + + + C8 + + + + + C9 + + + + + + + C10 + + + + + + + server + + + + + + + client + + + + diff --git a/images/interesting-rebase-3.png b/images/interesting-rebase-3.png index 45aeeca24..c8a0bdc4b 100644 Binary files a/images/interesting-rebase-3.png and b/images/interesting-rebase-3.png differ diff --git a/images/interesting-rebase-3.svg b/images/interesting-rebase-3.svg new file mode 100644 index 000000000..cb5e2e633 --- /dev/null +++ b/images/interesting-rebase-3.svg @@ -0,0 +1,92 @@ + + + + + + image/svg+xml + + images/interesting-rebase-3 + + + + + images/interesting-rebase-3 + Created with Sketch. + + + + C1 + + + + + + C2 + + + + + + + C5 + + + + + + + master + + + + + + + C6 + + + + + + + C8' + + + + + + C9' + + + + + C3 + + + + + + C4 + + + + + + C10 + + + + + + server + + + + + + + client + + + + diff --git a/images/interesting-rebase-4.png b/images/interesting-rebase-4.png index 44b6ca5f3..e815f7606 100644 Binary files a/images/interesting-rebase-4.png and b/images/interesting-rebase-4.png differ diff --git a/images/interesting-rebase-4.svg b/images/interesting-rebase-4.svg new file mode 100644 index 000000000..df0604b32 --- /dev/null +++ b/images/interesting-rebase-4.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + images/interesting-rebase-4 + + + + + images/interesting-rebase-4 + Created with Sketch. + + + + C1 + + + + + + C2 + + + + + + + C5 + + + + + + + master + + + + + + + C6 + + + + + + C8' + + + + + C9' + + + + + C3' + + + + + + C4' + + + + + + C10' + + + + + + C3 + + + + + + C4 + + + + + + C10 + + + + + + + server + + + + + + + client + + + + diff --git a/images/interesting-rebase-5.png b/images/interesting-rebase-5.png index aa0745dbe..9ee451a5c 100644 Binary files a/images/interesting-rebase-5.png and b/images/interesting-rebase-5.png differ diff --git a/images/interesting-rebase-5.svg b/images/interesting-rebase-5.svg new file mode 100644 index 000000000..18907ad93 --- /dev/null +++ b/images/interesting-rebase-5.svg @@ -0,0 +1,74 @@ + + + + + + image/svg+xml + + images/interesting-rebase-5 + + + + + images/interesting-rebase-5 + Created with Sketch. + + + + C1 + + + + + + C2 + + + + + + + C5 + + + + + + + master + + + + + + + C6 + + + + + C8' + + + + C9' + + + + + C3' + + + + + + C4' + + + + + + C10' + + + diff --git a/images/jb.png b/images/jb.png new file mode 100644 index 000000000..2ffe74a8b Binary files /dev/null and b/images/jb.png differ diff --git a/images/large-merges-1.png b/images/large-merges-1.png index d3ee025ae..d043166ab 100644 Binary files a/images/large-merges-1.png and b/images/large-merges-1.png differ diff --git a/images/large-merges-1.svg b/images/large-merges-1.svg new file mode 100644 index 000000000..534f87483 --- /dev/null +++ b/images/large-merges-1.svg @@ -0,0 +1,126 @@ + + + + + + image/svg+xml + + images/large-merges-1 + + + + + images/large-merges-1 + Created with Sketch. + + + + + master + + + + + + tv/rebase-stat + + + + + + + jk/clone-checkout + + + + + + + db/push-cleanup + + + + + + + js/notes + + + + + + + ps/blame + + + + + C1 + + + + + C2 + + + + + + + + + C3 + + + + C5 + + + + C7 + + + + C9 + + + + C11 + + + + + + C4 + + + + + + + C6 + + + + + + + C8 + + + + + + + C10 + + + + + + + C12 + + + + diff --git a/images/large-merges-2.png b/images/large-merges-2.png index 2d23e691b..71b07b77c 100644 Binary files a/images/large-merges-2.png and b/images/large-merges-2.png differ diff --git a/images/large-merges-2.svg b/images/large-merges-2.svg new file mode 100644 index 000000000..30288ecae --- /dev/null +++ b/images/large-merges-2.svg @@ -0,0 +1,172 @@ + + + + + + image/svg+xml + + images/large-merges-2 + + + + + images/large-merges-2 + Created with Sketch. + + + + + + master + + + + + + + tv/rebase-stat + + + + + + + jk/clone-checkout + + + + + + + db/push-cleanup + + + + + + + js/notes + + + + + + + seen + + + + + + + next + + + + + + + ps/blame + + + + + C1 + + + + + C2 + + + + + + + + + + + + C3 + + + + C5 + + + + C7 + + + + C9 + + + + C11 + + + + + + C4 + + + + + + C16 + + + + + C17 + + + + + C13 + + + + + C14 + + + + + C15 + + + + + + C6 + + + + + + + C8 + + + + + + + C10 + + + + + + + C12 + + + + + + diff --git a/images/lifecycle.png b/images/lifecycle.png index 922b02c09..68bf3a4e3 100644 Binary files a/images/lifecycle.png and b/images/lifecycle.png differ diff --git a/images/lifecycle.svg b/images/lifecycle.svg new file mode 100644 index 000000000..7e6ec6ab0 --- /dev/null +++ b/images/lifecycle.svg @@ -0,0 +1,49 @@ + + + + + + image/svg+xml + + images/lifecycle + + + + + images/lifecycle + Created with Sketch. + + + + + + + + + Modified + + + + + + + Edit the file + Add the file + Remove the file + Stage the file + + + Untracked + + + + Unmodified + + Commit + + + Staged + + + + diff --git a/images/local.png b/images/local.png index 1779acfbf..067e27e6f 100644 Binary files a/images/local.png and b/images/local.png differ diff --git a/images/local.svg b/images/local.svg new file mode 100644 index 000000000..dcc3a07ac --- /dev/null +++ b/images/local.svg @@ -0,0 +1,44 @@ + + + + + + image/svg+xml + + images/local + + + + images/local + Created with Sketch. + + + + Local Computer + + Version Database + Checkout + + + File + + + + Version 3 + + + + Version 2 + + + + Version 1 + + + + + + + + + diff --git a/images/lr-branches-1.png b/images/lr-branches-1.png index ad7c9c9a5..bafc60485 100644 Binary files a/images/lr-branches-1.png and b/images/lr-branches-1.png differ diff --git a/images/lr-branches-1.svg b/images/lr-branches-1.svg new file mode 100644 index 000000000..ad050292b --- /dev/null +++ b/images/lr-branches-1.svg @@ -0,0 +1,72 @@ + + + + + + image/svg+xml + + images/lr-branches-1 + + + + + images/lr-branches-1 + Created with Sketch. + + + + C1 + + + + + C2 + + + + + C3 + + + + + C4 + + + + + C5 + + + + + C6 + + + + + C7 + + + + + + master + + + + + + + develop + + + + + + + topic + + + + diff --git a/images/lr-branches-2.png b/images/lr-branches-2.png index 8db4bc080..bf8bdc05f 100644 Binary files a/images/lr-branches-2.png and b/images/lr-branches-2.png differ diff --git a/images/lr-branches-2.svg b/images/lr-branches-2.svg new file mode 100644 index 000000000..cafaeddea --- /dev/null +++ b/images/lr-branches-2.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + images/lr-branches-2 + + + + + images/lr-branches-2 + Created with Sketch. + + + + + + + + + master + develop + topic + + + + + + C1 + + + + + + C2 + + + + + C3 + + + + + C4 + + + + + C5 + + + + + C6 + + + + C7 + + + + diff --git a/images/managed-team-1.png b/images/managed-team-1.png index 489b6322e..e5525a794 100644 Binary files a/images/managed-team-1.png and b/images/managed-team-1.png differ diff --git a/images/managed-team-1.svg b/images/managed-team-1.svg new file mode 100644 index 000000000..12bffd398 --- /dev/null +++ b/images/managed-team-1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + images/managed-team-1 + + + + + images/managed-team-1 + Created with Sketch. + + + + 4b078 + + + + + 1edee + + + + + + 33009 + + + + + + 85127 + + + + + e5b0f + + + + + featureB + + + + + master + + + + featureA + + diff --git a/images/managed-team-2.png b/images/managed-team-2.png index 25c2db2b6..725e7e9bd 100644 Binary files a/images/managed-team-2.png and b/images/managed-team-2.png differ diff --git a/images/managed-team-2.svg b/images/managed-team-2.svg new file mode 100644 index 000000000..7318ac6ab --- /dev/null +++ b/images/managed-team-2.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + images/managed-team-2 + + + + + images/managed-team-2 + Created with Sketch. + + + + + 4b078 + + + + + 1edee + + + + + + 33009 + + + + + + + aad88 + + + + + + + 774b3 + + + + + + + 85127 + + + + + + cd685 + + + + + fba9a + + + + + e5b0f + + + + + + + + + + + featureB + + + + + + + master + + + + + + + + + + + + featureA + + + + + origin/featureA + + + + origin/featureBee + + + diff --git a/images/managed-team-3.png b/images/managed-team-3.png index a8a08a707..a20e9e3ef 100644 Binary files a/images/managed-team-3.png and b/images/managed-team-3.png differ diff --git a/images/managed-team-3.svg b/images/managed-team-3.svg new file mode 100644 index 000000000..bb65880d9 --- /dev/null +++ b/images/managed-team-3.svg @@ -0,0 +1,116 @@ + + + + + + image/svg+xml + + images/managed-team-3 + + + + + images/managed-team-3 + Created with Sketch. + + + + + + 4b078 + + + + + 1edee + + + + + + 33009 + + + + + + + aad88 + + + + + + + 774b3 + + + + + + 5399e + + + + + + 85127 + + + + + + cd685 + + + + + fba9a + + + + + e5b0f + + + + + + + + + featureB + + + + + + + master + + + + + + + + + + featureA + + + origin/featureBee + + + + origin/featureA + + + + + + + + origin/master + + diff --git a/images/managed-team-flow.png b/images/managed-team-flow.png index 6d83ac4d7..039cb9a65 100644 Binary files a/images/managed-team-flow.png and b/images/managed-team-flow.png differ diff --git a/images/managed-team-flow.svg b/images/managed-team-flow.svg new file mode 100644 index 000000000..1ae8a02f2 --- /dev/null +++ b/images/managed-team-flow.svg @@ -0,0 +1,538 @@ + + + + + + + + image/svg+xml + + images/managed-team-flow + + + + + images/managed-team-flow + Created with Sketch. + + + + John + + + + + John + + + + Josie + + + + + Josie + + + + Jessica + + + + + Jessica + + + + + git commit(A) + git commit(B) + git fetch origin + + git fetch origin + + git fetch origin + git push origin featureA + + git push origin featureA + + git push origin featureA + + git push origin featureBee + + git push origin featureB:featureBee + + + git commit(A) + + git commit(B) + + + git merge(B) + + git merge(A) + + git commit(A) + + git merge(A) + + + + server:featureA + + + + server:featureBee + + + + server:featureA + + + + server:featureBee + + + diff --git a/images/merging-workflows-1.png b/images/merging-workflows-1.png index 461de6e22..1149352fe 100644 Binary files a/images/merging-workflows-1.png and b/images/merging-workflows-1.png differ diff --git a/images/merging-workflows-1.svg b/images/merging-workflows-1.svg new file mode 100644 index 000000000..622cb69b1 --- /dev/null +++ b/images/merging-workflows-1.svg @@ -0,0 +1,84 @@ + + + + + + image/svg+xml + + images/merging-workflows-1 + + + + + images/merging-workflows-1 + Created with Sketch. + + + + + C1 + + + + + + + C2 + + + + + + C7 + + + + + + C3 + + + + + + + C4 + + + + + + + C5 + + + + + + + C6 + + + + + + + master + + + + + + + ruby_client + + + + + + + php_client + + + + diff --git a/images/merging-workflows-2.png b/images/merging-workflows-2.png index 5a0d1fcf8..fc6bc7713 100644 Binary files a/images/merging-workflows-2.png and b/images/merging-workflows-2.png differ diff --git a/images/merging-workflows-2.svg b/images/merging-workflows-2.svg new file mode 100644 index 000000000..a96571cea --- /dev/null +++ b/images/merging-workflows-2.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/merging-workflows-2 + + + + + images/merging-workflows-2 + Created with Sketch. + + + + + C1 + + + + + + + C2 + + + + + + + C7 + + + + + + + C3 + + + + + + + C4 + + + + + + + + C9 + + + + + + + + C8 + + + + + + + C5 + + + + + + + C6 + + + + + + + master + + + + + + + ruby_client + + + + + php_client + + + + diff --git a/images/merging-workflows-3.png b/images/merging-workflows-3.png index f3a32367c..4e5850019 100644 Binary files a/images/merging-workflows-3.png and b/images/merging-workflows-3.png differ diff --git a/images/merging-workflows-3.svg b/images/merging-workflows-3.svg new file mode 100644 index 000000000..4d96149ba --- /dev/null +++ b/images/merging-workflows-3.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + images/merging-workflows-3 + + + + + images/merging-workflows-3 + Created with Sketch. + + + + + C1 + + + + + + C2 + + + + + C5 + + + + + + C3 + + + + + + C4 + + + + + + develop + + + + + + + master + + + + + + + ruby_client + + + + diff --git a/images/merging-workflows-4.png b/images/merging-workflows-4.png index 2ad04c13f..dc611a6a2 100644 Binary files a/images/merging-workflows-4.png and b/images/merging-workflows-4.png differ diff --git a/images/merging-workflows-4.svg b/images/merging-workflows-4.svg new file mode 100644 index 000000000..03d27b90d --- /dev/null +++ b/images/merging-workflows-4.svg @@ -0,0 +1,74 @@ + + + + + + image/svg+xml + + images/merging-workflows-4 + + + + + images/merging-workflows-4 + Created with Sketch. + + + + + C1 + + + + + + C2 + + + + + C5 + + + + + + C3 + + + + + + + C4 + + + + + + + C6 + + + + + + develop + + + + + + + master + + + + + + + ruby_client + + + + diff --git a/images/merging-workflows-5.png b/images/merging-workflows-5.png index 151cbd278..4a91da4aa 100644 Binary files a/images/merging-workflows-5.png and b/images/merging-workflows-5.png differ diff --git a/images/merging-workflows-5.svg b/images/merging-workflows-5.svg new file mode 100644 index 000000000..d817f71e1 --- /dev/null +++ b/images/merging-workflows-5.svg @@ -0,0 +1,74 @@ + + + + + + image/svg+xml + + images/merging-workflows-5 + + + + + images/merging-workflows-5 + Created with Sketch. + + + + + C1 + + + + + + C2 + + + + + C5 + + + + + + C3 + + + + + + + C4 + + + + + + + C6 + + + + + + develop + + + + + + + master + + + + + + + ruby_client + + + + diff --git a/images/perils-of-rebasing-1.png b/images/perils-of-rebasing-1.png index 013e04bfe..f9312184f 100644 Binary files a/images/perils-of-rebasing-1.png and b/images/perils-of-rebasing-1.png differ diff --git a/images/perils-of-rebasing-1.svg b/images/perils-of-rebasing-1.svg new file mode 100644 index 000000000..ee813308e --- /dev/null +++ b/images/perils-of-rebasing-1.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + images/perils-of-rebasing-1 + + + + + images/perils-of-rebasing-1 + Created with Sketch. + + + + + + C1 + + + + + + master + + + + + C1 + + + + + C2 + + + + + C3 + + + + + + master + + + + + + + teamone/master + + + My Computer + git.team1.ourcompany.com + + diff --git a/images/perils-of-rebasing-2.png b/images/perils-of-rebasing-2.png index 2c14ccdff..6e6f55850 100644 Binary files a/images/perils-of-rebasing-2.png and b/images/perils-of-rebasing-2.png differ diff --git a/images/perils-of-rebasing-2.svg b/images/perils-of-rebasing-2.svg new file mode 100644 index 000000000..210dd4958 --- /dev/null +++ b/images/perils-of-rebasing-2.svg @@ -0,0 +1,106 @@ + + + + + + image/svg+xml + + images/perils-of-rebasing-2 + + + + + images/perils-of-rebasing-2 + Created with Sketch. + + + + + + + C1 + + + + master + + + + C4 + + + + + + C5 + + + + + C6 + + + My Computer + git.team1.ourcompany.com + + + + C1 + + + + + C3 + + + + + + + C7 + + + + + + + C4 + + + + + + + + C5 + + + + + + + C6 + + + + + + + master + + + + + teamone/master + + + + + + + C2 + + + + + diff --git a/images/perils-of-rebasing-3.png b/images/perils-of-rebasing-3.png index 505407a00..1f0603a17 100644 Binary files a/images/perils-of-rebasing-3.png and b/images/perils-of-rebasing-3.png differ diff --git a/images/perils-of-rebasing-3.svg b/images/perils-of-rebasing-3.svg new file mode 100644 index 000000000..1ad6f7da0 --- /dev/null +++ b/images/perils-of-rebasing-3.svg @@ -0,0 +1,138 @@ + + + + + + image/svg+xml + + images/perils-of-rebasing-3 + + + + + images/perils-of-rebasing-3 + Created with Sketch. + + + + + + + + C1 + + + + + + master + + + + + + C4' + + + + + + C5 + + + + + + + + C4 + + + + + + + + C6 + + + + + + + + C1 + + + + + + C2 + + + + + + + C3 + + + + + + + + C7 + + + + + + + C4' + + + + + + + C4 + + + + + + + C5 + + + + + + + + + C6 + + + + + + + + master + + + + + + + teamone/master + + + + My Computer + git.team1.ourcompany.com + + + diff --git a/images/perils-of-rebasing-4.png b/images/perils-of-rebasing-4.png index 01b9dbba3..a1e23f3e3 100644 Binary files a/images/perils-of-rebasing-4.png and b/images/perils-of-rebasing-4.png differ diff --git a/images/perils-of-rebasing-4.svg b/images/perils-of-rebasing-4.svg new file mode 100644 index 000000000..f4d24b7f9 --- /dev/null +++ b/images/perils-of-rebasing-4.svg @@ -0,0 +1,144 @@ + + + + + + image/svg+xml + + images/perils-of-rebasing-4 + + + + + images/perils-of-rebasing-4 + Created with Sketch. + + + + + + + C1 + + + + + master + + + + + + C4' + + + + + + + + C5 + + + + + + + C4 + + + + + + + + C6 + + + + + + + + C1 + + + + + + C2 + + + + + + + C3 + + + + + + + + C7 + + + + + + + + C8 + + + + + + + C4' + + + + + + + C4 + + + + + + + + C5 + + + + + + + C6 + + + + + + + master + + + + + + + + + teamone/master + + + + My Computer + git.team1.ourcompany.com + + diff --git a/images/perils-of-rebasing-5.png b/images/perils-of-rebasing-5.png index 20a189297..27c860d0f 100644 Binary files a/images/perils-of-rebasing-5.png and b/images/perils-of-rebasing-5.png differ diff --git a/images/perils-of-rebasing-5.svg b/images/perils-of-rebasing-5.svg new file mode 100644 index 000000000..fcdf683f4 --- /dev/null +++ b/images/perils-of-rebasing-5.svg @@ -0,0 +1,111 @@ + + + + + + image/svg+xml + + images/perils-of-rebasing-5 + + + + + images/perils-of-rebasing-5 + Created with Sketch. + + + + + + C1 + + + + + + master + + + + + + + C4' + + + + + + + C5 + + + + + + + + C4 + + + + + + + + C6 + + + + + + + + + C1 + + + + + + C4' + + + + + + + + + C2' + + + + + + + C3' + + + + + + + C5 + + + + + + + master + + + + + teamone/master + + + My Computer + git.team1.ourcompany.com + diff --git a/images/public-small-1.png b/images/public-small-1.png index efcb90d6b..ae0a86652 100644 Binary files a/images/public-small-1.png and b/images/public-small-1.png differ diff --git a/images/public-small-1.svg b/images/public-small-1.svg new file mode 100644 index 000000000..b93842285 --- /dev/null +++ b/images/public-small-1.svg @@ -0,0 +1,82 @@ + + + + + + image/svg+xml + + images/public-small-1 + + + + + images/public-small-1 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + 33009 + + + + + + + 0d708 + + + + + + e5b0f + + + + + a2de3 + + + + + + master + + + + + + + featureA + + + + + + + featureB + + + + + + + + + origin/master + + + + diff --git a/images/public-small-2.png b/images/public-small-2.png index 9dd40631b..ba614c1a1 100644 Binary files a/images/public-small-2.png and b/images/public-small-2.png differ diff --git a/images/public-small-2.svg b/images/public-small-2.svg new file mode 100644 index 000000000..d1aa124c5 --- /dev/null +++ b/images/public-small-2.svg @@ -0,0 +1,76 @@ + + + + + + image/svg+xml + + images/public-small-2 + + + + + images/public-small-2 + Created with Sketch. + + + + 4b078 + + + + + 1edee + + + + + 33009 + + + + + + 5399e + + + + + + e5b0f + + + + + dee6b + + + + + master + + + + + + featureA + + + + + + + featureB + + + + + + + + + origin/master + + + + diff --git a/images/public-small-3.png b/images/public-small-3.png index fa06f77e4..dfe200de2 100644 Binary files a/images/public-small-3.png and b/images/public-small-3.png differ diff --git a/images/public-small-3.svg b/images/public-small-3.svg new file mode 100644 index 000000000..2f31fcc76 --- /dev/null +++ b/images/public-small-3.svg @@ -0,0 +1,108 @@ + + + + + + image/svg+xml + + images/public-small-3 + + + + + + + + + + images/public-small-3 + Created with Sketch. + + + + + + 4b078 + + + + + + 1edee + + + + + + + 33009 + + + + + + + 5399e + + + + + + + 17f4d + + + + + + + e5b0f + + + + + + + dee6b + + + + + + + master + + + + + + + featureA + + + + + + + featureB + + + + + + + featureBv2 + + + + + + + + + origin/master + + + + + diff --git a/images/rebasing-1.png b/images/rebasing-1.png index cd3efa163..983110829 100644 Binary files a/images/rebasing-1.png and b/images/rebasing-1.png differ diff --git a/images/rebasing-1.svg b/images/rebasing-1.svg new file mode 100644 index 000000000..85d75a475 --- /dev/null +++ b/images/rebasing-1.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + images/rebasing-1 + + + + + images/rebasing-1 + Created with Sketch. + + + + + 0b743 + + + + + + a6b4c + + + + + f42c5 + + + + + + e43a6 + + + + + + 5ddae + + + + + master + + + + + + ruby_client + + + + diff --git a/images/rebasing-2.png b/images/rebasing-2.png index 55ca410be..406f3d084 100644 Binary files a/images/rebasing-2.png and b/images/rebasing-2.png differ diff --git a/images/rebasing-2.svg b/images/rebasing-2.svg new file mode 100644 index 000000000..087b845f7 --- /dev/null +++ b/images/rebasing-2.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + images/rebasing-2 + + + + + images/rebasing-2 + Created with Sketch. + + + + + 0b743 + + + + + + a6b4c + + + + + + f42c5 + + + + + + a0a41 + + + + + + master + + + + + + + + + e43a6 + + + + + + + 5ddae + + + + + + + ruby_client + + + + + diff --git a/images/remote-branches-1.png b/images/remote-branches-1.png index 759538f46..40f0cef47 100644 Binary files a/images/remote-branches-1.png and b/images/remote-branches-1.png differ diff --git a/images/remote-branches-1.svg b/images/remote-branches-1.svg new file mode 100644 index 000000000..1e466427b --- /dev/null +++ b/images/remote-branches-1.svg @@ -0,0 +1,78 @@ + + + + + + image/svg+xml + + images/remote-branches-1 + + + + + images/remote-branches-1 + Created with Sketch. + + + + + + 0b743 + + + + + a6b4c + + + + + f4265 + + + + + + master + + + git.ourcompany.com + git clone janedoe@git.ourcompany.com:project.git + + + + 0b743 + + + + + + a6b4c + + + + + + + f4265 + + + + + + + master + + + + + + + origin/master + + + My Computer + Remote branch + Local branch + + diff --git a/images/remote-branches-2.png b/images/remote-branches-2.png index 14cfe56c2..6d5117ee0 100644 Binary files a/images/remote-branches-2.png and b/images/remote-branches-2.png differ diff --git a/images/remote-branches-2.svg b/images/remote-branches-2.svg new file mode 100644 index 000000000..b76e0fc90 --- /dev/null +++ b/images/remote-branches-2.svg @@ -0,0 +1,95 @@ + + + + + + image/svg+xml + + images/remote-branches-2 + + + + + images/remote-branches-2 + Created with Sketch. + + + + + 0b743 + + + + + a6b4c + + + + + f4265 + + + + + 31b8e + + + + + 190a3 + + + + + + master + + + + + + + 0b743 + + + + + a6b4c + + + + + f4265 + + + + + a38de + + + + + 893cf + + + + + + master + + + + + + + origin/master + + + + + + My Computer + git.ourcompany.com + Someone else pushes + + diff --git a/images/remote-branches-3.png b/images/remote-branches-3.png index 6d1993e4e..cfc942d62 100644 Binary files a/images/remote-branches-3.png and b/images/remote-branches-3.png differ diff --git a/images/remote-branches-3.svg b/images/remote-branches-3.svg new file mode 100644 index 000000000..452ae2249 --- /dev/null +++ b/images/remote-branches-3.svg @@ -0,0 +1,104 @@ + + + + + + image/svg+xml + + images/remote-branches-3 + + + + + images/remote-branches-3 + Created with Sketch. + + + + 0b743 + + + + + a6b4c + + + + + + f4265 + + + + + + + 31b8e + + + + + 190a3 + + + + a38de + + + + + 893cf + + + + + + master + + + + + + + origin/master + + + + My Computer + + + 0b743 + + + + + a6b4c + + + + + f4265 + + + + + 31b8e + + + + + 190a3 + + + + + + master + + + + git.ourcompany.com + git fetch origin + + + diff --git a/images/remote-branches-4.png b/images/remote-branches-4.png index b4183bf18..a493bffcd 100644 Binary files a/images/remote-branches-4.png and b/images/remote-branches-4.png differ diff --git a/images/remote-branches-4.svg b/images/remote-branches-4.svg new file mode 100644 index 000000000..8b7bd0cbc --- /dev/null +++ b/images/remote-branches-4.svg @@ -0,0 +1,113 @@ + + + + + + image/svg+xml + + images/remote-branches-4 + + + + + images/remote-branches-4 + Created with Sketch. + + + + 0b743 + + + + + a6b4c + + + + + + f4265 + + + + + + + 31b8e + + + + + 190a3 + + + + a38de + + + + + 893cf + + + + + master + + + + + + origin/master + + + + My Computer + git remote add teamone git://git.team1.ourcompany.com + + + + f4265 + + + + + 31b8e + + + + + 190a3 + + + + + + master + + + + git.ourcompany.com + origin + + + + f4265 + + + + + 31b8e + + + + + + master + + + + git.team1.ourcompany.com + teamone + + diff --git a/images/remote-branches-5.png b/images/remote-branches-5.png index be2282399..cad3fe64c 100644 Binary files a/images/remote-branches-5.png and b/images/remote-branches-5.png differ diff --git a/images/remote-branches-5.svg b/images/remote-branches-5.svg new file mode 100644 index 000000000..0ba0a0473 --- /dev/null +++ b/images/remote-branches-5.svg @@ -0,0 +1,127 @@ + + + + + + image/svg+xml + + images/remote-branches-5 + + + + + images/remote-branches-5 + Created with Sketch. + + + + + + 0b743 + + + + + a6b4c + + + + + + f4265 + + + + + + + 31b8e + + + + + 190a3 + + + + a38de + + + + + 893cf + + + + + + master + + + + + + + origin/master + + + + + + teamone/master + + + + My Computer + git fetch teamone + + + + + f4265 + + + + + 31b8e + + + + + 190a3 + + + + + + master + + + + + git.ourcompany.com + origin + + + + + f4265 + + + + + 31b8e + + + + + + master + + + + + git.team1.ourcompany.com + teamone + + diff --git a/images/replace1.png b/images/replace1.png index f5a23f7fc..fb24e9119 100644 Binary files a/images/replace1.png and b/images/replace1.png differ diff --git a/images/replace1.svg b/images/replace1.svg new file mode 100644 index 000000000..7475392db --- /dev/null +++ b/images/replace1.svg @@ -0,0 +1,53 @@ + + + + + + image/svg+xml + + images/replace1 + + + + + images/replace1 + Created with Sketch. + + + + + ef989 + fifth + + + + c6e1e + fourth + + + + + 9c68f + third + + + + + 94570 + second + + + + + c1822 + first + + + + + + master + + + + diff --git a/images/replace2.png b/images/replace2.png index 5b03076c8..ae3b0a34e 100644 Binary files a/images/replace2.png and b/images/replace2.png differ diff --git a/images/replace2.svg b/images/replace2.svg new file mode 100644 index 000000000..30410b0e1 --- /dev/null +++ b/images/replace2.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/replace2 + + + + + images/replace2 + Created with Sketch. + + + + + ef989 + fifth + + + + + + c6e1e + fourth + + + + + + + 9c68f + third + + + + + + 94570 + second + + + + c1822 + first + + + + + + master + + + + + + + history + + + + diff --git a/images/replace3.png b/images/replace3.png index 5c3191cd9..da5469fe2 100644 Binary files a/images/replace3.png and b/images/replace3.png differ diff --git a/images/replace3.svg b/images/replace3.svg new file mode 100644 index 000000000..193ac7980 --- /dev/null +++ b/images/replace3.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + images/replace3 + + + + + images/replace3 + Created with Sketch. + + + + + 622e8 + instructions + + + + + + c6e1e + fourth + + + + + + + 9c68f + third + + + + + + 94570 + second + + + + c1822 + first + + + + + + history + + + + + + + ef989 + fifth + + + + + + master + + + + + + diff --git a/images/replace4.png b/images/replace4.png index 553820c0a..22d456da3 100644 Binary files a/images/replace4.png and b/images/replace4.png differ diff --git a/images/replace4.svg b/images/replace4.svg new file mode 100644 index 000000000..9181110f7 --- /dev/null +++ b/images/replace4.svg @@ -0,0 +1,95 @@ + + + + + + image/svg+xml + + images/replace4 + + + + + images/replace4 + Created with Sketch. + + + + + + + rebase + + + + + + + + ef989 + fifth + + + + + + + master + + + + + + + e146b + fifth + + + + + c6e1e + fourth + + + + + + + history + + + + + + + 81a70 + fourth + + + + + 622e8 + instructions + + + + + + 9c68f + third + + + + + + 94570 + second + + + + c1822 + first + + + + diff --git a/images/replace5.png b/images/replace5.png index 41e7cd7bd..f4b49ec9f 100644 Binary files a/images/replace5.png and b/images/replace5.png differ diff --git a/images/replace5.svg b/images/replace5.svg new file mode 100644 index 000000000..dae52b664 --- /dev/null +++ b/images/replace5.svg @@ -0,0 +1,89 @@ + + + + + + image/svg+xml + + images/replace5 + + + + + images/replace5 + Created with Sketch. + + + + + + + master + + + + + + + e146b + fifth + + + + + replace + + + + + + + 81a70 + fourth + + + + + 622e8 + instructions + + + + + + + + c6e1e + fourth + + + + + + + history + + + + + + + 9c68f + third + + + + + + 94570 + second + + + + c1822 + first + + + + + diff --git a/images/rerere1.png b/images/rerere1.png index 34ab3b7b7..33386cd21 100644 Binary files a/images/rerere1.png and b/images/rerere1.png differ diff --git a/images/rerere1.svg b/images/rerere1.svg new file mode 100644 index 000000000..7bf25b2ea --- /dev/null +++ b/images/rerere1.svg @@ -0,0 +1,52 @@ + + + + + + image/svg+xml + + images/rerere1 + + + + + images/rerere1 + Created with Sketch. + + + + + + master + + + + + + + hello world + + + + + + + hola world + + + + + + + hello mundo + + + + + + + i18n-world + + + + diff --git a/images/rerere2.png b/images/rerere2.png index 85dd47f4b..da2f88c53 100644 Binary files a/images/rerere2.png and b/images/rerere2.png differ diff --git a/images/rerere2.svg b/images/rerere2.svg new file mode 100644 index 000000000..041e26850 --- /dev/null +++ b/images/rerere2.svg @@ -0,0 +1,72 @@ + + + + + + image/svg+xml + + images/rerere2 + + + + + images/rerere2 + Created with Sketch. + + + + + + + hello world + + + + + + + hola world + + + + + + + + hola mundo + + + + + hello mundo + + + + + + + + rerere cache + + + + - puts ‘hola world’ - puts ‘hello mundo’ ++ puts ‘hola mundo’ + + + + + + + master + + + + + + + i18-world + + + + + diff --git a/images/rerere3.png b/images/rerere3.png index b299ac74c..d20f7a059 100644 Binary files a/images/rerere3.png and b/images/rerere3.png differ diff --git a/images/rerere3.svg b/images/rerere3.svg new file mode 100644 index 000000000..61bd3427c --- /dev/null +++ b/images/rerere3.svg @@ -0,0 +1,123 @@ + + + + + + image/svg+xml + + images/rerere3 + + + + + images/rerere3 + Created with Sketch. + + + + + + + + + + + + + hello world + + + + + + + hola world + + + + + + + master + + + + + + + + rebase + + + + + hello mundo + + + + + + + + + + hola mundo + + + + + + rerere cache + + + + - puts ‘hola world’ - puts ‘hello mundo’ ++ puts ‘hola mundo’ + + + + + + + i18-world + + + + + diff --git a/images/reset-checkout.png b/images/reset-checkout.png index fe036345e..72e7c7f0f 100644 Binary files a/images/reset-checkout.png and b/images/reset-checkout.png differ diff --git a/images/reset-checkout.svg b/images/reset-checkout.svg new file mode 100644 index 000000000..c7f619e5c --- /dev/null +++ b/images/reset-checkout.svg @@ -0,0 +1,118 @@ + + + + + + image/svg+xml + + images/reset-checkout + + + + + images/reset-checkout + Created with Sketch. + + before command + + + commit A + + + + + commit B + + + + + master + + + + + + + develop + + + + + + + HEAD + + + + + + + commit A + + + + + + commit B + + + + + + + HEAD + + + + + + + master + + + + + + + develop + + + + after reset + + + after checkout + + + + commit A + + + + + commit B + + + + + + master + + + + + + + develop + + + + + + + HEAD + + + + + diff --git a/images/reset-ex1.png b/images/reset-ex1.png index 2ffd68b25..f08aa941f 100644 Binary files a/images/reset-ex1.png and b/images/reset-ex1.png differ diff --git a/images/reset-ex1.svg b/images/reset-ex1.svg new file mode 100644 index 000000000..768227f30 --- /dev/null +++ b/images/reset-ex1.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + images/reset-ex1 + + + + + images/reset-ex1 + Created with Sketch. + + + + + + Index + + + + + + + + HEAD + + + + ? + + Git Repository + + + + + + file.txtv1 + + + + + + WorkingDirectory + + + + + + + HEAD + + + + master + + + diff --git a/images/reset-ex2.png b/images/reset-ex2.png index f4ffd2a7a..e6c6aa2b1 100644 Binary files a/images/reset-ex2.png and b/images/reset-ex2.png differ diff --git a/images/reset-ex2.svg b/images/reset-ex2.svg new file mode 100644 index 000000000..9ba054f23 --- /dev/null +++ b/images/reset-ex2.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + images/reset-ex2 + + + + + images/reset-ex2 + Created with Sketch. + + + + + + + HEAD + + + + + git add + + + + + file.txtv1 + + + + + + WorkingDirectory + + + + + + + + Index + + + + + file.txtv1 + + + ? + Git Repository + + + + + + HEAD + + + + master + + + + + diff --git a/images/reset-ex3.png b/images/reset-ex3.png index 742749332..07a6c91ac 100644 Binary files a/images/reset-ex3.png and b/images/reset-ex3.png differ diff --git a/images/reset-ex3.svg b/images/reset-ex3.svg new file mode 100644 index 000000000..44c643a95 --- /dev/null +++ b/images/reset-ex3.svg @@ -0,0 +1,87 @@ + + + + + + image/svg+xml + + images/reset-ex3 + + + + + images/reset-ex3 + Created with Sketch. + + + + + + + + HEAD + + + + master + + + + Git Repository + git commit + + + + + file.txtv1 + + + + + + WorkingDirectory + + + + + + + + + HEAD + + + + eb43bf8 + + + file.txtv1 + + + + + + + + Index + + + + + file.txtv1 + + + + + + eb43bf8 + + + file.txtv1 + + + + + + + diff --git a/images/reset-ex4.png b/images/reset-ex4.png index 3cfbf7fc7..8c4c01d10 100644 Binary files a/images/reset-ex4.png and b/images/reset-ex4.png differ diff --git a/images/reset-ex4.svg b/images/reset-ex4.svg new file mode 100644 index 000000000..6fa4a42cd --- /dev/null +++ b/images/reset-ex4.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + images/reset-ex4 + + + + + images/reset-ex4 + Created with Sketch. + + + + + + + Index + + + + + + + + HEAD + + + + + Git Repository + + + file.txtv2 + + + + + + + + WorkingDirectory + + + + + file.txtv1 + + edit file + eb43bf8 + eb43bf8 + + + file.txtv1 + + + + file.txtv1 + + + + + + + HEAD + + + + master + + + diff --git a/images/reset-ex5.png b/images/reset-ex5.png index c21a2534b..bb03b1acb 100644 Binary files a/images/reset-ex5.png and b/images/reset-ex5.png differ diff --git a/images/reset-ex5.svg b/images/reset-ex5.svg new file mode 100644 index 000000000..fc7067d3e --- /dev/null +++ b/images/reset-ex5.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + images/reset-ex5 + + + + + images/reset-ex5 + Created with Sketch. + + + + + + + Index + + + + + + + + HEAD + + + + + Git Repository + + + file.txtv2 + + + + + + + + WorkingDirectory + + + git add + eb43bf8 + eb43bf8 + + + file.txtv1 + + + + file.txtv1 + + + + file.txtv2 + + + + + + + HEAD + + + + master + + + diff --git a/images/reset-ex6.png b/images/reset-ex6.png index c64cc38f3..55d64c3ae 100644 Binary files a/images/reset-ex6.png and b/images/reset-ex6.png differ diff --git a/images/reset-ex6.svg b/images/reset-ex6.svg new file mode 100644 index 000000000..4038dc115 --- /dev/null +++ b/images/reset-ex6.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/reset-ex6 + + + + + images/reset-ex6 + Created with Sketch. + + + Git Repository + git commit + + + + + file.txtv2 + + + + + + + + WorkingDirectory + + + + + + + + + Index + + + + + file.txtv2 + + + + 9e5e6a4 + + + + + + HEAD + + + + + + file.txtv2 + + + + + + + + + eb43bf8 + + + + file.txtv1 + + + + + + 9e5e6a4 + + + + file.txtv2 + + + + + + + + + HEAD + + + + master + + + diff --git a/images/reset-hard.png b/images/reset-hard.png index a9da7cedc..c9668bb02 100644 Binary files a/images/reset-hard.png and b/images/reset-hard.png differ diff --git a/images/reset-hard.svg b/images/reset-hard.svg new file mode 100644 index 000000000..f5fe4271a --- /dev/null +++ b/images/reset-hard.svg @@ -0,0 +1,119 @@ + + + + + + image/svg+xml + + images/reset-hard + + + + + images/reset-hard + Created with Sketch. + + + + + + + HEAD + + + + master + + + + git reset --hard HEAD~ + + + 1 + + + + + file.txtv2 + + + + + + + + WorkingDirectory + + + + + + + + + Index + + + + + file.txtv2 + + + + 9e5e6a4 + + + + + + HEAD + + + + + + file.txtv2 + + + + 2 + + + + 3 + + + + + + + + eb43bf8 + + + + file.txtv1 + + + + + + 9e5e6a4 + + + + file.txtv2 + + + + + 38eb946 + + + file.txtv3 + + + Git Repository + + + diff --git a/images/reset-mixed.png b/images/reset-mixed.png index 0266fe511..15db78130 100644 Binary files a/images/reset-mixed.png and b/images/reset-mixed.png differ diff --git a/images/reset-mixed.svg b/images/reset-mixed.svg new file mode 100644 index 000000000..c65c0e194 --- /dev/null +++ b/images/reset-mixed.svg @@ -0,0 +1,113 @@ + + + + + + image/svg+xml + + images/reset-mixed + + + + + images/reset-mixed + Created with Sketch. + + git reset [--mixed] HEAD~ + + + + + HEAD + + + + master + + + + + + 1 + + + + + file.txtv3 + + + + + + + + WorkingDirectory + + + + + + + + + Index + + + + + file.txtv2 + + + + 9e5e6a4 + + + + + + HEAD + + + + + + file.txtv2 + + + + 2 + + + + + + + + eb43bf8 + + + + file.txtv1 + + + + + + 9e5e6a4 + + + + file.txtv2 + + + + + 38eb946 + + + file.txtv3 + + + Git Repository + + diff --git a/images/reset-path1.png b/images/reset-path1.png index 1672e02bd..66929fb74 100644 Binary files a/images/reset-path1.png and b/images/reset-path1.png differ diff --git a/images/reset-path1.svg b/images/reset-path1.svg new file mode 100644 index 000000000..f4f774bd3 --- /dev/null +++ b/images/reset-path1.svg @@ -0,0 +1,76 @@ + + + + + + image/svg+xml + + images/reset-path1 + + + + + images/reset-path1 + Created with Sketch. + + git reset file.txt + + + + + + Index + + + + + + + + HEAD + + + + + Git Repository + + + file.txtv2 + + + + + + + + WorkingDirectory + + + + + file.txtv1 + + eb43bf8 + eb43bf8 + + + file.txtv1 + + + + file.txtv1 + + + + + + HEAD + + + + master + + + + + diff --git a/images/reset-path2.png b/images/reset-path2.png index 08308e5e6..d4106fd57 100644 Binary files a/images/reset-path2.png and b/images/reset-path2.png differ diff --git a/images/reset-path2.svg b/images/reset-path2.svg new file mode 100644 index 000000000..575e0d655 --- /dev/null +++ b/images/reset-path2.svg @@ -0,0 +1,76 @@ + + + + + + image/svg+xml + + images/reset-path2 + + + + + images/reset-path2 + Created with Sketch. + + git add file.txt + + + + + + Index + + + + + + + + HEAD + + + + + Git Repository + + + file.txtv2 + + + + + + + + WorkingDirectory + + + + + file.txtv2 + + eb43bf8 + eb43bf8 + + + file.txtv1 + + + + file.txtv1 + + + + + + HEAD + + + + master + + + + + diff --git a/images/reset-path3.png b/images/reset-path3.png index e01f80aeb..71e60b8cb 100644 Binary files a/images/reset-path3.png and b/images/reset-path3.png differ diff --git a/images/reset-path3.svg b/images/reset-path3.svg new file mode 100644 index 000000000..9565e24f1 --- /dev/null +++ b/images/reset-path3.svg @@ -0,0 +1,107 @@ + + + + + + image/svg+xml + + images/reset-path3 + + + + + images/reset-path3 + Created with Sketch. + + + git reset eb43 -- file.txt + + + + + HEAD + + + + master + + + + + + + + eb43bf8 + + + + file.txtv1 + + + + + + 9e5e6a4 + + + + file.txtv2 + + + + + 38eb946 + + + file.txtv3 + + + Git Repository + + + + + file.txtv3 + + + + + + + + WorkingDirectory + + + + + + + + + Index + + + + + file.txtv1 + + + + 38eb946 + + + + + + HEAD + + + + + + file.txtv3 + + + + + diff --git a/images/reset-soft.png b/images/reset-soft.png index 831d9f6f5..b50985956 100644 Binary files a/images/reset-soft.png and b/images/reset-soft.png differ diff --git a/images/reset-soft.svg b/images/reset-soft.svg new file mode 100644 index 000000000..09fe219d5 --- /dev/null +++ b/images/reset-soft.svg @@ -0,0 +1,106 @@ + + + + + + image/svg+xml + + images/reset-soft + + + + + images/reset-soft + Created with Sketch. + + git reset --soft HEAD~ + + + + + + + + eb43bf8 + + + + file.txtv1 + + + + + 9e5e6a4 + + + + file.txtv2 + + + + 38eb946 + + + file.txtv3 + + + + Git Repository + + + + + + HEAD + + + + master + + + + + + + file.txtv3 + + + + + + + + WorkingDirectory + + + + + 9e5e6a4 + + + file.txtv2 + + + + + + + HEAD + + + + + + + + + + Index + + + + + file.txtv3 + + + diff --git a/images/reset-squash-r1.png b/images/reset-squash-r1.png index e703a3097..b328fc23a 100644 Binary files a/images/reset-squash-r1.png and b/images/reset-squash-r1.png differ diff --git a/images/reset-squash-r1.svg b/images/reset-squash-r1.svg new file mode 100644 index 000000000..7aa6bf2e9 --- /dev/null +++ b/images/reset-squash-r1.svg @@ -0,0 +1,132 @@ + + + + + + image/svg+xml + + images/reset-squash-r1 + + + + + images/reset-squash-r1 + Created with Sketch. + + Git Repository + + + + + + + HEAD + + + + master + + + + + + + + file-a.txt v1 + + eb43bf8 + + + + 9e5e6a4 + + + file-a.txt v2 + + + + file-b.txt v1 + + + + + 38eb946 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + + + + + WorkingDirectory + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + Index + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + 38eb946 + + + + + + + HEAD + + + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + diff --git a/images/reset-squash-r2.png b/images/reset-squash-r2.png index 8b3bd4439..61a24472a 100644 Binary files a/images/reset-squash-r2.png and b/images/reset-squash-r2.png differ diff --git a/images/reset-squash-r2.svg b/images/reset-squash-r2.svg new file mode 100644 index 000000000..478592656 --- /dev/null +++ b/images/reset-squash-r2.svg @@ -0,0 +1,139 @@ + + + + + + image/svg+xml + + images/reset-squash-r2 + + + + + images/reset-squash-r2 + Created with Sketch. + + 38eb946 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + git reset --soft HEAD~2 + + + Git Repository + + + + + file-a.txt v1 + + eb43bf8 + + + + + + 9e5e6a4 + + + file-a.txt v2 + + + + file-b.txt v1 + + + + + + + HEAD + + + + master + + + + + 38eb946 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + + + + WorkingDirectory + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + Index + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + + HEAD + + + + + + file-a.txt v1 + + eb43bf8 + + + + diff --git a/images/reset-squash-r3.png b/images/reset-squash-r3.png index 9f5f9b2f5..510e027a9 100644 Binary files a/images/reset-squash-r3.png and b/images/reset-squash-r3.png differ diff --git a/images/reset-squash-r3.svg b/images/reset-squash-r3.svg new file mode 100644 index 000000000..144f0955d --- /dev/null +++ b/images/reset-squash-r3.svg @@ -0,0 +1,147 @@ + + + + + + image/svg+xml + + images/reset-squash-r3 + + + + + images/reset-squash-r3 + Created with Sketch. + + + git commit + + + + + + + Git Repository + + + + + file-a.txt v1 + + eb43bf8 + + + + 9e5e6a4 + + + file-a.txt v2 + + + + file-b.txt v1 + + + + + + + HEAD + + + + master + + + + + + + + + + WorkingDirectory + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + + Index + + + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + 68aef35 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + + + HEAD + + + + + + + 68aef35 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + + 38eb946 + + + + file-a.txt v3 + + + + file-b.txt v1 + + + + + diff --git a/images/reset-start.png b/images/reset-start.png index 70b3fb064..2d7b15232 100644 Binary files a/images/reset-start.png and b/images/reset-start.png differ diff --git a/images/reset-start.svg b/images/reset-start.svg new file mode 100644 index 000000000..380481424 --- /dev/null +++ b/images/reset-start.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/reset-start + + + + + images/reset-start + Created with Sketch. + + + + + + + eb43bf8 + + + file.txtv1 + + + + + 9e5e6a4 + + + file.txtv2 + + + + + 38eb946 + + + file.txtv3 + + + Git Repository + + + + + HEAD + + + + master + + + + + + file.txtv3 + + + + + + + + WorkingDirectory + + + + + + + + + Index + + + + + file.txtv3 + + + + 38eb946 + + + + + + HEAD + + + + + + file.txtv3 + + + + diff --git a/images/reset-workflow.png b/images/reset-workflow.png index 1c01e0d55..c741d4bd3 100644 Binary files a/images/reset-workflow.png and b/images/reset-workflow.png differ diff --git a/images/reset-workflow.svg b/images/reset-workflow.svg new file mode 100644 index 000000000..35be798cb --- /dev/null +++ b/images/reset-workflow.svg @@ -0,0 +1,48 @@ + + + + + + image/svg+xml + + images/reset-workflow + + + + + images/reset-workflow + Created with Sketch. + + + + + + + + + + Index + + + + HEAD + + + + WorkingDirectory + + + + Checkout the project + + + + Commit + + + + Stage Files + + + + diff --git a/images/small-team-1.png b/images/small-team-1.png index d13654ec5..3dd5be188 100644 Binary files a/images/small-team-1.png and b/images/small-team-1.png differ diff --git a/images/small-team-1.svg b/images/small-team-1.svg new file mode 100644 index 000000000..e33ae1b18 --- /dev/null +++ b/images/small-team-1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + images/small-team-1 + + + + + images/small-team-1 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + 738ee + + + + + + + fbff5 + + + + + + + origin/master + + + + + + + master + + + + diff --git a/images/small-team-2.png b/images/small-team-2.png index 1af627874..f738c75b5 100644 Binary files a/images/small-team-2.png and b/images/small-team-2.png differ diff --git a/images/small-team-2.svg b/images/small-team-2.svg new file mode 100644 index 000000000..78e7d23a9 --- /dev/null +++ b/images/small-team-2.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/small-team-2 + + + + + images/small-team-2 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + 738ee + + + + + + + + 72bbc + + + + + + + fbff5 + + + + + + + origin/master + + + + + + + master + + + + diff --git a/images/small-team-3.png b/images/small-team-3.png index 3b01de8ba..31d0f7268 100644 Binary files a/images/small-team-3.png and b/images/small-team-3.png differ diff --git a/images/small-team-3.svg b/images/small-team-3.svg new file mode 100644 index 000000000..1a2dbd429 --- /dev/null +++ b/images/small-team-3.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + images/small-team-3 + + + + + images/small-team-3 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + 738ee + + + + + + + + 72bbc + + + + + + + fbff5 + + + + + + + origin/master + + + + + + + master + + + + diff --git a/images/small-team-4.png b/images/small-team-4.png index b5e8c00b2..a649b97e7 100644 Binary files a/images/small-team-4.png and b/images/small-team-4.png differ diff --git a/images/small-team-4.svg b/images/small-team-4.svg new file mode 100644 index 000000000..3cd495ed3 --- /dev/null +++ b/images/small-team-4.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + images/small-team-4 + + + + + images/small-team-4 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + fbff5 + + + + + + + 8149a + + + + + + + 23ac6 + + + + + + + 4af42 + + + + + + + origin/master + + + + + + master + + + + + + issue54 + + + + diff --git a/images/small-team-5.png b/images/small-team-5.png index e0215e4fb..8219ac302 100644 Binary files a/images/small-team-5.png and b/images/small-team-5.png differ diff --git a/images/small-team-5.svg b/images/small-team-5.svg new file mode 100644 index 000000000..8279e6825 --- /dev/null +++ b/images/small-team-5.svg @@ -0,0 +1,90 @@ + + + + + + image/svg+xml + + images/small-team-5 + + + + + images/small-team-5 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + fbff5 + + + + + + 738ee + + + + + + + + 72bbc + + + + + + + 8149a + + + + + + + 23ac6 + + + + + + + 4af42 + + + + + + + origin/master + + + + + + + master + + + + + + + issue54 + + + + diff --git a/images/small-team-6.png b/images/small-team-6.png index 357944415..23bc4e1e3 100644 Binary files a/images/small-team-6.png and b/images/small-team-6.png differ diff --git a/images/small-team-6.svg b/images/small-team-6.svg new file mode 100644 index 000000000..0c0804b79 --- /dev/null +++ b/images/small-team-6.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/small-team-6 + + + + + images/small-team-6 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + fbff5 + + + + + + + 738ee + + + + + + + + 72bbc + + + + + + + + 8059c + + + + + + + 8149a + + + + + + + 23ac6 + + + + + + + 4af42 + + + + + + + origin/master + + + + + + + master + + + + + + + issue54 + + + + diff --git a/images/small-team-7.png b/images/small-team-7.png index 6bbbc2d8b..64ae230a6 100644 Binary files a/images/small-team-7.png and b/images/small-team-7.png differ diff --git a/images/small-team-7.svg b/images/small-team-7.svg new file mode 100644 index 000000000..726076274 --- /dev/null +++ b/images/small-team-7.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/small-team-7 + + + + + images/small-team-7 + Created with Sketch. + + + + 4b078 + + + + + + 1edee + + + + + + + fbff5 + + + + + + + 738ee + + + + + + + + 72bbc + + + + + + + + 8059c + + + + + + + 8149a + + + + + + + 23ac6 + + + + + + + 4af42 + + + + + + + origin/master + + + + + + + master + + + + + + + issue54 + + + + diff --git a/images/small-team-flow.png b/images/small-team-flow.png index c8589ba6b..12fe526f6 100644 Binary files a/images/small-team-flow.png and b/images/small-team-flow.png differ diff --git a/images/small-team-flow.svg b/images/small-team-flow.svg new file mode 100644 index 000000000..93a805c16 --- /dev/null +++ b/images/small-team-flow.svg @@ -0,0 +1,400 @@ + + + + + + + + image/svg+xml + + images/small-team-flow + + + + + images/small-team-flow + Created with Sketch. + + + + + + Server + + + + + + John + + + + + + Jessica + + + + + + + git clone + + + git commit + + + git clone + + + + git fetch + + + + git push + + + + git push + + + + git push + + + + git fetch + + + + git fetch + + + + + git commit + + + + git merge + + + + git merge + + + + + + Server + + + + + + John + + + + + + Jessica + + + + diff --git a/images/smudge.png b/images/smudge.png index d86aa05c7..7d4d84bea 100644 Binary files a/images/smudge.png and b/images/smudge.png differ diff --git a/images/smudge.svg b/images/smudge.svg new file mode 100644 index 000000000..26b7f8232 --- /dev/null +++ b/images/smudge.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + images/smudge + + + + + images/smudge + Created with Sketch. + + + + + fileA.txt + + + + + fileA.txt' + + + + fileB.txt' + + + + fileB.txt + + + + fileC.rb + + + + fileC.rb + + Staging Area + Working Directory + *.txt Filter + + + smudge + + + + clean + + + + + + + + + diff --git a/images/snapshots.png b/images/snapshots.png index 1036a4245..0c9e0e28c 100644 Binary files a/images/snapshots.png and b/images/snapshots.png differ diff --git a/images/snapshots.svg b/images/snapshots.svg new file mode 100644 index 000000000..446fb7513 --- /dev/null +++ b/images/snapshots.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + images/snapshots + + + + + images/snapshots + Created with Sketch. + + + + + + + + + Version 1 + + Version 2 + + Version 3 + + Version 4 + + Version 5 + + + + File A + + + + File A + + + + + A1 + + + + + C1 + + + + C2 + + + + B1 + + + + A2 + + + + A2 + + + + B2 + + + C3 + + + File B + + + + File C + + + Checkins Over Time + + + B + + + + A1 + + + + C2 + + + + B + + + diff --git a/images/symbols.svg b/images/symbols.svg new file mode 100644 index 000000000..164a1ebb3 --- /dev/null +++ b/images/symbols.svg @@ -0,0 +1,158 @@ + + + + images/symbols + Created with Sketch. + + + + + C6 + + + + + + v1.0 + + + + + + HEAD + + + + + + tree + + + + + + Version 5 + + + + + + integration + manager + + + + + + developer + public + + + + + + Staging + Area + + + + + + 9c68f + + + + + + c2b9e + + + + + + HEAD + + + + + + Working + Directory + + + + + + size + 92ec2 + Scott + Scott + + + commit + + tree + author + committer + + + The initial commit of my project + + + + + + size + 5b1d3 README + 911e7 LICENSE + cba0a test.rb + + + tree + + blob + blob + blob + + + + + + size + + + blob + + + == Testing library + + This library is used to test + Ruby projects. + + + + + + hello mundo + + + + + + fbff5 + + + + + + 738ee + + + + + + fba9a + + + + diff --git a/images/topic-branches-1.png b/images/topic-branches-1.png index 3bdca0dc1..d7bb02b64 100644 Binary files a/images/topic-branches-1.png and b/images/topic-branches-1.png differ diff --git a/images/topic-branches-1.svg b/images/topic-branches-1.svg new file mode 100644 index 000000000..f181fbfa7 --- /dev/null +++ b/images/topic-branches-1.svg @@ -0,0 +1,102 @@ + + + + + + image/svg+xml + + images/topic-branches-1 + + + + + images/topic-branches-1 + Created with Sketch. + + + + C0 + + + + + C1 + + + + + C3 + + + + + C9 + + + + + C10 + + + + + C2 + + + + + C4 + + + + + C5 + + + + + C6 + + + + + C12 + + + + + C13 + + + + + C7 + + + + + C8 + + + + + C11 + + + + master + + + + iss91 + + + + iss91v2 + + + + dumbidea + + + diff --git a/images/topic-branches-2.png b/images/topic-branches-2.png index fe139d99e..1d789a2fb 100644 Binary files a/images/topic-branches-2.png and b/images/topic-branches-2.png differ diff --git a/images/topic-branches-2.svg b/images/topic-branches-2.svg new file mode 100644 index 000000000..a17db5e4f --- /dev/null +++ b/images/topic-branches-2.svg @@ -0,0 +1,118 @@ + + + + + + image/svg+xml + + images/topic-branches-2 + + + + + images/topic-branches-2 + Created with Sketch. + + + + C0 + + + + + + C1 + + + + + + + C3 + + + + + + + C9 + + + + + + + C10 + + + + + + + C2 + + + + + + + C4 + + + + + + + C13 + + + + + + + + C14 + + + + + + + C12 + + + + + master + + + + + + C7 + + + + + + + C8 + + + + + + + C11 + + + + + iss91v2 + + + + dumbidea + + + diff --git a/images/two-branches.png b/images/two-branches.png index aa6377a08..9cdbdccc5 100644 Binary files a/images/two-branches.png and b/images/two-branches.png differ diff --git a/images/two-branches.svg b/images/two-branches.svg new file mode 100644 index 000000000..ded4572cf --- /dev/null +++ b/images/two-branches.svg @@ -0,0 +1,51 @@ + + + + + + image/svg+xml + + images/two-branches + + + + + images/two-branches + Created with Sketch. + + + + + + master + + + + + + + testing + + + + + + + f30ab + + + + + + + + + 34ac2 + + + + + 98ca9 + + + diff --git a/images/undomerge-reset.png b/images/undomerge-reset.png index 3ffcc6244..a0a3503c7 100644 Binary files a/images/undomerge-reset.png and b/images/undomerge-reset.png differ diff --git a/images/undomerge-reset.svg b/images/undomerge-reset.svg new file mode 100644 index 000000000..e9a0f8abf --- /dev/null +++ b/images/undomerge-reset.svg @@ -0,0 +1,83 @@ + + + + + + image/svg+xml + + images/undomerge-reset + + + + + images/undomerge-reset + Created with Sketch. + + + + C1 + + + + + + + C2 + + + + + + + C5 + + + + + C3 + + + + + C4 + + + + + + C6 + + + + + + + + M + + + + + + + + master + + + + + + + HEAD + + + + + + + + topic + + + + diff --git a/images/undomerge-revert.png b/images/undomerge-revert.png index 87cd7c93d..d84d717fe 100644 Binary files a/images/undomerge-revert.png and b/images/undomerge-revert.png differ diff --git a/images/undomerge-revert.svg b/images/undomerge-revert.svg new file mode 100644 index 000000000..df81ae265 --- /dev/null +++ b/images/undomerge-revert.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + images/undomerge-revert + + + + + images/undomerge-revert + Created with Sketch. + + + + C1 + + + + + + + + C2 + + + + + + + C5 + + + + + C3 + + + + + C4 + + + + + + C6 + + + + + + + M + + + + + + ^M + + + + + + + master + + + + + + + HEAD + + + + + + + + topic + + + + diff --git a/images/undomerge-revert2.png b/images/undomerge-revert2.png index dc5727eab..e93127f9d 100644 Binary files a/images/undomerge-revert2.png and b/images/undomerge-revert2.png differ diff --git a/images/undomerge-revert2.svg b/images/undomerge-revert2.svg new file mode 100644 index 000000000..146d80ebf --- /dev/null +++ b/images/undomerge-revert2.svg @@ -0,0 +1,99 @@ + + + + + + image/svg+xml + + images/undomerge-revert2 + + + + + images/undomerge-revert2 + Created with Sketch. + + + + C1 + + + + + + + + C2 + + + + + + + C5 + + + + + C3 + + + + + C4 + + + + + + C6 + + + + + + C7 + + + + + + C8 + + + + + + M + + + + + + ^M + + + + + + + master + + + + + + + HEAD + + + + + + + + topic + + + + diff --git a/images/undomerge-revert3.png b/images/undomerge-revert3.png index 71f94a63f..31206d152 100644 Binary files a/images/undomerge-revert3.png and b/images/undomerge-revert3.png differ diff --git a/images/undomerge-revert3.svg b/images/undomerge-revert3.svg new file mode 100644 index 000000000..7459de450 --- /dev/null +++ b/images/undomerge-revert3.svg @@ -0,0 +1,106 @@ + + + + + + image/svg+xml + + images/undomerge-revert3 + + + + + images/undomerge-revert3 + Created with Sketch. + + + + C1 + + + + + + + + C2 + + + + + + + C5 + + + + + C3 + + + + + C4 + + + + + + C6 + + + + + + C7 + + + + + + ^^M + + + + + + + C8 + + + + + + M + + + + + + ^M + + + + + + + master + + + + + + + HEAD + + + + + + + + topic + + + + diff --git a/images/undomerge-start.png b/images/undomerge-start.png index 518a71d88..8d286fab6 100644 Binary files a/images/undomerge-start.png and b/images/undomerge-start.png differ diff --git a/images/undomerge-start.svg b/images/undomerge-start.svg new file mode 100644 index 000000000..8a9e3bb0d --- /dev/null +++ b/images/undomerge-start.svg @@ -0,0 +1,79 @@ + + + + + + image/svg+xml + + images/undomerge-start + + + + + images/undomerge-start + Created with Sketch. + + + + C1 + + + + + + + + C2 + + + + + + + C5 + + + + + C3 + + + + + C4 + + + + + + C6 + + + + + + M + + + + + + master + + + + + + + HEAD + + + + + + + topic + + + + diff --git a/images/vs-1.png b/images/vs-1.png deleted file mode 100644 index 312cde3b5..000000000 Binary files a/images/vs-1.png and /dev/null differ diff --git a/images/vs-2.png b/images/vs-2.png deleted file mode 100644 index 78d404c26..000000000 Binary files a/images/vs-2.png and /dev/null differ diff --git a/index.asc b/index.asc index 2df4a6b13..9618359ad 100644 --- a/index.asc +++ b/index.asc @@ -1,3 +1,3 @@ [#index] [index] -= Index +== Index diff --git a/progit.asc b/progit.asc index 30d0c5ea5..9774d00c1 100644 --- a/progit.asc +++ b/progit.asc @@ -1,5 +1,4 @@ -Pro Git -======= += Pro Git Scott Chacon; Ben Straub :doctype: book :docinfo: @@ -9,8 +8,6 @@ Scott Chacon; Ben Straub :front-cover-image: image:book/cover.png[width=1050,height=1600] :icons: font -ifdef::ebook-format[:leveloffset: -1] - include::book/license.asc[] include::book/preface_schacon.asc[] @@ -49,4 +46,4 @@ include::B-embedding-git-in-your-applications.asc[] include::C-git-commands.asc[] -ifndef::ebook-format[include::index.asc[]] +ifdef::backend-pdf[include::index.asc[]] diff --git a/script/tag_on_master b/script/tag_on_master deleted file mode 100755 index 6757a2997..000000000 --- a/script/tag_on_master +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# This is for running on Travis. It automatically tags any merge to Master as a release in the 2.1.x series. -if [[ $TRAVIS_PULL_REQUEST != 'false' || "$TRAVIS_BRANCH" != 'master' ]]; then - # Don't run on pull requests - echo 'This only runs on a merge to master.' - exit 0 -fi - -# Compute the next tag number -LASTPATCH=$(git describe --tags | cut -d- -f1 | cut -d. -f3) -PATCH=$(($LASTPATCH+1)) -echo $PATCH - -# Create a tag -curl -H "Authorization: token $GITHUB_KEY" \ - -X POST \ - -d "{\"ref\":\"refs/tags/2.1.$PATCH\", \"sha\":\"$TRAVIS_COMMIT\"}" \ - https://api.github.com/repos/progit/progit2/git/refs diff --git a/status.json b/status.json index fc15757a8..03a8d8307 100644 --- a/status.json +++ b/status.json @@ -88,12 +88,10 @@ "sections/client-hg.asc": 0, "sections/client-p4.asc": 0, "sections/client-svn.asc": 0, - "sections/client-tfs.asc": 0, "sections/import-custom.asc": 0, "sections/import-hg.asc": 0, "sections/import-p4.asc": 0, - "sections/import-svn.asc": 0, - "sections/import-tfs.asc": 0 + "sections/import-svn.asc": 0 }, "10-git-internals": { "1-git-internals.asc": 0, @@ -109,15 +107,19 @@ "A-git-in-other-environments": { "1-git-other-environments.asc": 0, "sections/bash.asc": 0, - "sections/eclipse.asc": 0, "sections/guis.asc": 0, + "sections/jetbrainsides.asc": 0, "sections/powershell.asc": 0, + "sections/sublimetext.asc": 0, "sections/visualstudio.asc": 0, + "sections/visualstudiocode.asc": 0, "sections/zsh.asc": 0 }, "B-embedding-git": { "1-embedding-git.asc": 0, "sections/command-line.asc": 0, + "sections/dulwich.asc": 0, + "sections/go-git.asc": 0, "sections/jgit.asc": 0, "sections/libgit2.asc": 0 },