andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 1 | # Git Cookbook |
| 2 | |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 3 | A collection of git recipes to do common git tasks. |
| 4 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 5 | See also [Git Tips](git_tips.md). |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 6 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 7 | [TOC] |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 8 | |
| 9 | ## Introduction |
| 10 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 11 | This is designed to be a cookbook for common command sequences/tasks relating to |
qyearsley | c0dc6f4 | 2016-12-02 22:13:39 | [diff] [blame] | 12 | git, git-cl, and how they work with Chromium development. It might be a little |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 13 | light on explanations. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 14 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 15 | If you are new to git, or do not have much experience with a distributed version |
| 16 | control system, you should also check out |
| 17 | [The Git Community Book](http://book.git-scm.com/) for an overview of basic git |
| 18 | concepts and general git usage. Knowing what git means by branches, commits, |
| 19 | reverts, and resets (as opposed to what SVN means by them) will help make the |
| 20 | following much more understandable. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 21 | |
Aaron Gable | bbc51dc | 2017-05-17 18:45:54 | [diff] [blame] | 22 | ## Chromium-specific Git Extensions |
| 23 | |
| 24 | Chromium ships a large number of git extensions in depot_tools. Some (like |
| 25 | `git cl`) are required for the Chromium development workflow, while others |
| 26 | (like `git map-branches`) are simple utilities to make your life easier. |
| 27 | Please take a look at the full |
| 28 | [depot_tools tutorial](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html), |
| 29 | and at the extensive |
| 30 | [man pages](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools.html) |
| 31 | for all the extensions. |
| 32 | |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 33 | ## Excluding file(s) from git-cl, while preserving them for later use |
| 34 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 35 | Since git-cl assumes that the diff between your current branch and its tracking |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 36 | branch is what should be used for the CL, the goal is to remove the unwanted |
| 37 | files from the current branch, and preserve them in another branch. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 38 | |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 39 | ### Method #1: Reset your current branch, and selectively commit files |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 40 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 41 | 1. `git log` See the list of your commits. Find the hash of the last commit |
| 42 | before your changes. |
| 43 | 1. `git reset --soft abcdef` where abcdef is the hash found in the step above. |
| 44 | 1. `git commit <files_for_this_cl> -m "files to upload"` commit the files you |
| 45 | want included in the CL here. |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 46 | 1. `git new-branch new_branch_name` Create a new branch for the |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 47 | files that you want to exclude. |
| 48 | 1. `git commit -a -m "preserved files"` Commit the rest of the files. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 49 | |
| 50 | ### Method #2: Create a new branch, reset, then commit files to preserve |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 51 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 52 | This method creates a new branch from your current one to preserve your changes. |
| 53 | The commits on the new branch are undone, and then only the files you want to |
| 54 | preserve are recommitted. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 55 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 56 | 1. `git checkout -b new_branch_name` This preserves your old files. |
| 57 | 1. `git log` See the list of your commits. Find the hash of the last commit |
| 58 | before your changes. |
| 59 | 1. `git reset --soft abcdef` Where abcdef is the hash found in the step above. |
| 60 | 1. `git commit <files_to_preserve> -m "preserved files"` Commit the found files |
| 61 | into the `new_branch_name`. |
| 62 | |
| 63 | Then revert your files however you'd like in your old branch. The files listed |
| 64 | in step 4 will be saved in `new_branch_name` |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 65 | |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 66 | ### Method #3: Cherry-pick changes into review branches |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 67 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 68 | If you are systematic in creating separate local commits for independent |
| 69 | changes, you can make a number of different changes in the same client and then |
| 70 | cherry-pick each one into a separate review branch. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 71 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 72 | 1. Make and commit a set of independent changes. |
| 73 | 1. `git log` # see the hashes for each of your commits. |
| 74 | 1. repeat checkout, cherry-pick, upload steps for each change1..n |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 75 | 1. `git new-branch review-changeN` Create a new review branch |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 76 | tracking origin |
| 77 | 1. `git cherry-pick <hash of change N>` |
| 78 | 1. `git cl upload` |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 79 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 80 | If a change needs updating due to review comments, you can go back to your main |
| 81 | working branch, update the commit, and re-cherry-pick it into the review branch. |
| 82 | |
| 83 | 1. `git checkout <working branch>` |
| 84 | 1. Make changes. |
| 85 | 1. If the commit you want to update is the most recent one: |
| 86 | 1. `git commit --amend <files>` |
| 87 | 1. If not: |
| 88 | 1. `git commit <files>` |
| 89 | 1. `git rebase -i origin` # use interactive rebase to squash the new |
| 90 | commit into the old one. |
| 91 | 1. `git log` # observe new hash for the change |
| 92 | 1. `git checkout review-changeN` |
| 93 | 1. `git reset --hard` # remove the previous version of the change |
| 94 | 1. `cherry-pick <new hash of change N>` |
| 95 | 1. `git cl upload` |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 96 | |
| 97 | ## Sharing code between multiple machines |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 98 | |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 99 | Assume Windows computer named vista, and a Linux one named penguin. |
| 100 | Prerequisite: both machines have git clones of the main git tree. |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 101 | |
| 102 | ```shell |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 103 | vista$ git remote add linux ssh://penguin/path/to/git/repo |
| 104 | vista$ git fetch linux |
| 105 | vista$ git branch -a # should show "linux/branchname" |
| 106 | vista$ git checkout -b foobar linux/foobar |
| 107 | vista$ hack hack hack; git commit -a |
| 108 | vista$ git push linux # push branch back to linux |
| 109 | penguin$ git reset --hard # update with new stuff in branch |
| 110 | ``` |
| 111 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 112 | Note that, by default, `gclient sync` will update all remotes. If your other |
| 113 | machine (i.e., `penguin` in the above example) is not always available, |
| 114 | `gclient sync` will timeout and fail trying to reach it. To fix this, you may |
| 115 | exclude your machine from being fetched by default: |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 116 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 117 | vista$ git config --bool remote.linux.skipDefaultUpdate true |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 118 | |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 119 | ## Reverting commits |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 120 | |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 121 | The command `git revert X` patches in the inverse of a particular commit. |
| 122 | Using this command is one way of making a revert: |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 123 | |
| 124 | ```shell |
| 125 | git checkout origin # start with trunk |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 126 | git revert abcdef |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 127 | git cl upload |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 128 | ``` |
| 129 | |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 130 | ## Retrieving, or diffing against an old file revision |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 131 | |
| 132 | Git works in terms of commits, not files. Thus, working with the history of a |
| 133 | single file requires modified version of the show and diff commands. |
| 134 | |
| 135 | ```shell |
| 136 | # Find the commit you want in the file's commit log. |
| 137 | git log path/to/file |
| 138 | # This prints out the file contents at commit 123abc. |
| 139 | git show 123abc:path/to/file |
| 140 | # Diff the current version against path/to/file against the version at |
| 141 | # path/to/file |
| 142 | git diff 123abc -- path/to/file |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 143 | ``` |
| 144 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 145 | When invoking `git show` or `git diff`, the `path/to/file` is **not relative the |
| 146 | the current directory**. It must be the full path from the directory where the |
| 147 | .git directory lives. This is different from invoking `git log` which |
| 148 | understands relative paths. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 149 | |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 150 | ## Reusing a Git mirror |
| 151 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 152 | If you have a nearby copy of a Git repo, you can quickly bootstrap your copy |
| 153 | from that one then adjust it to point it at the real upstream one. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 154 | |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 155 | 1. Clone a nearby copy of the code you want: `git clone coworker-machine:/path/to/repo` |
| 156 | 1. Change the URL your copy fetches from to point at the real git repo: |
Quinten Yearsley | 893fd75 | 2017-07-13 15:34:46 | [diff] [blame] | 157 | `git set-url origin https://chromium.googlesource.com/chromium/src.git` |
andybons | 22afb31 | 2015-08-31 02:24:51 | [diff] [blame] | 158 | 1. Update your copy: `git fetch` |
| 159 | 1. Delete any extra branches that you picked up in the initial clone: |
| 160 | `git prune origin` |