[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 @title Arcanist User Guide: Commit Ranges 2 @group userguide 3 4 Explains how commit ranges work in Arcanist. 5 6 This is an advanced user guide which covers a complicated topic in detail. If 7 you're just getting started, you don't need to look at this yet. Instead, start 8 with the @{article:Arcanist User Guide}. 9 10 = Overview = 11 12 //In Subversion, `arc` commands always operate on the uncommitted changes in the 13 working copy. If you use Subversion, this document is not relevant to you.// 14 15 In Git and Mercurial, many `arc` commands (notably, `arc diff`) operate on a 16 range of commits beginning with some commit you specify and ending with the 17 working copy state. 18 19 Since the end of the range is fixed (the working copy state), you only need to 20 specify the beginning of the range. This is called the "base commit". You can do 21 this explicitly when you run commands: 22 23 $ arc diff HEAD^ # git: just the most recent commit 24 $ arc diff .^ # hg: just the most recent commit 25 26 You can also configure `arc` so it defaults to some base commit, or figures out 27 the base commit using a (potentially sophisticated) ruleset. 28 29 NOTE: This document describes a new mechanism for determining base commits. It 30 is subject to change. There are currently several other mechanisms available as 31 well, mentioned in other documents. As this mechanism matures, it should replace 32 other mechanisms and defaults. 33 34 = Configuring Base Commit Rules = 35 36 Base commit rule configuration may be more complicated than you expect. This is 37 because people use many different workflows in Git and Mercurial, and have very 38 different expectations about what base commit `arc` should pick when run. To 39 make matters worse, some of the most common ways of thinking about which commits 40 represent a change are incompatible when selecting defaults. 41 42 Historically, we tried to use a number of heuristics and simpler approaches to 43 determine the base commit, but there is so much diversity in how people think 44 about version control and what they expect to happen that some users were always 45 unhappy. 46 47 Although ruleset configuration is fairly complex, it's powerful enough that you 48 should be able to get exactly the behavior you want. 49 50 To determine the base commit, `arc` processes //rules// one at a time until it 51 gets a match (a rule which identifies a valid commit). The first match is the 52 base commit that is used to determine the beginning of the commit range. 53 54 A //rule// looks like this: 55 56 arc:upstream 57 58 A rule may //match//, meaning that it identifies some valid commit in the 59 working copy, or //fail//, meaning that it does not identify a valid commit. For 60 instance, the rule `arc:upstream` will //match// if the current Git branch 61 tracks an upstream branch, but //fail// if the current Git branch does not track 62 an upstream branch, or the working copy isn't a Git working copy. When a rule 63 fails, processing continues with the next rule. Some rules can never match but 64 produce useful side effects instead. These are described below. 65 66 A //ruleset// is a comma-separated list of rules: 67 68 arc:upstream, arc:prompt 69 70 `arc` reads five rulesets: 71 72 # `args`, specified with `--base <ruleset>` on the command line when you run 73 a command. This ruleset is processed first. 74 # `local`, specified with `arc set-config --local base <ruleset>`. This 75 ruleset is local to the working copy where it is set, and is processed 76 second. 77 # `project`, specified by setting the "base" key in `.arcconfig`. This 78 ruleset is bound to the project where it is configured, and is processed 79 third. 80 # `global`, specified with `arc set-config base <ruleset>`. This ruleset is 81 global for the current user, and is processed fourth. 82 # `system`, specified in a system-wide configuration file. This ruleset is 83 global for all users on the system, and is processed last. 84 85 The rules in each ruleset are processed one at a time until a valid base commit 86 is found. Valid rules are listed below. In this list, "*" means "any string". 87 88 - `git:*` Use the specified symbolic commit, if it exists. 89 - `git:merge-base(*)` Use the merge-base of HEAD and the specified symbolic 90 commit, if it exists. 91 - `git:branch-unique(*)` Attempt to select changes unique to this branch (that 92 is, changes between the branch point and HEAD). This rule is complicated and 93 has limitations, see below for a detailed description. 94 - `hg:*` Use the specified symbolic commit, if it exists. 95 - `hg:gca(*)` Use the greatest common ancestor of `.` and the specified 96 symbolic commit, if it exists. 97 - `arc:upstream` Use the merge-base of the current branch's upstream and 98 HEAD, if it exists. (git-only) 99 - `arc:outgoing` Use the most recent non-outgoing ancestor of the working 100 copy parent. (hg-only) 101 - `arc:exec(*)` Execute the specified command. The command should determine 102 the base revision to use and print it to stdout, then exit with return code 103 0. If the command exits with another return code, the rule will fail. The 104 command will be executed with the root directory of the working copy as the 105 current working directory. 106 - `arc:bookmark` Use the most recent non-outgoing ancestor of the working 107 copy parent or the most recent bookmark, whichever is more recent. This 108 rule is complicated and has limitations, see below for a detailed 109 description. 110 - `arc:amended` Use the current commit (`HEAD` in Git, or `.` in Mercurial) if 111 it has been amended to include a "Differential Revision:" field. Otherwise, 112 fail. 113 - `arc:prompt` Prompt the user to provide a commit. 114 - `arc:empty` Use the empty state (as though the repository were completely 115 empty, the range will include every commit that is an ancestor of the 116 working copy). 117 - `arc:this` Use the current commit. This means `.` under Mercurial and HEAD 118 under Git. 119 120 Rules are also available which change the processing order of rulesets: 121 122 - `arc:args`, `arc:local`, `arc:project`, `arc:global`, `arc:system` Stop 123 processing the current ruleset and begin processing the specified ruleset. 124 The current ruleset will resume processing after the specified ruleset is 125 exhausted. 126 - `arc:yield` Stop processing the current ruleset and begin processing the 127 next ruleset. The current ruleset will resume processing after other 128 rulesets have processed or when it next appears in the processing order, 129 whichever comes first. 130 - `arc:halt` Stops processing all rules. This will cause the command you ran 131 to fail, but can be used to avoid running rules which would otherwise 132 be processed later. 133 134 Additionally, there are some rules which are probably useful mostly for testing 135 or debugging rulesets: 136 137 - `arc:verbose` Turns on verbose logging of rule processing. 138 - `arc:skip` This rule has no effect. 139 - `literal:*` Use the specified commit literally. Almost certainly wrong in 140 production rules. 141 142 = Examples = 143 144 Diff against `origin/master` if it exists, and prompt if it doesn't: 145 146 git:merge-base(origin/master), arc:prompt 147 148 Diff against the upstream if it exists, or just use the last commit if it 149 doesn't: 150 151 arc:upstream, git:HEAD^ 152 153 As a user, ignore project rules and always use my rules: 154 155 (local) arc:global, arc:halt 156 157 As a project maintainer, respect user rules over project rules: 158 159 (project) arc:yield, <defaults> 160 161 Debug your rules: 162 163 $ arc diff --base arc:verbose 164 165 Understand rules processing: 166 167 $ arc which 168 $ arc which --base '<ruleset>' 169 $ arc which --base 'arc:verbose, <ruleset>' 170 171 = Detailed Rule Descriptions = 172 173 Some rules have complex operation, described here in more detail. These rules 174 are advanced features for expert users wishing to optimize their workflow and 175 save a little typing. You do not need to understand the behavior of these rules 176 to use `arc` (you can always specify a base commit explicitly). 177 178 == git:branch-unique(*) == 179 180 This rule only works in Git. 181 182 This rule tries to find commits that are unique to the current branch. It is 183 most likely to be useful if you develop using one branch per feature, update 184 changes by amending commits (instead of stacking commits) and merge changes by 185 rebasing (instead of merging). 186 187 The rule operates by first determining the merge-base of the specified commit 188 and HEAD, if it exists. If no such commit exists, the rule fails. If such a 189 commit exists, the rule counts how many branches contain HEAD, then walks from 190 HEAD to the merge-base commit, counting how many branches contain each commit. 191 It stops when it finds a commit which appears on more branches than HEAD, 192 or when it reaches the merge-base commit. 193 194 This rule works well for trees that look like this: 195 196 | * Commit B1, on branch "subfeature" (HEAD) 197 | / 198 | * Commit A1, on branch "feature" 199 |/ 200 * Commit M1, on branch "master" 201 | 202 203 This tree represents using feature branches to develop one feature ("feature"), 204 and then creating a sub-branch to develop a dependent feature ("subfeature"). 205 206 Normally, if you run `arc diff` on branch "subfeature" (with HEAD at `B1`), a 207 rule like `arc:merge-base(master)` will select `M1` as the base commit and thus 208 incorrectly include `A1` in the commit range. 209 210 For trees like this, `git:branch-unique(master)` will instead select `A1` as the 211 base commit (because it is the first commit between `B1` and `M1` which appears 212 on more branches than `B1` -- `B1` appears on only "subfeature" while `A1` 213 appears on "subfeature" and "feature") and include only `B1` in the commit 214 range. 215 216 The rule will also do the right thing when run from "feature" in this case. 217 218 However, this rule will select the wrong commit range in some cases. For 219 instance, it will do the wrong thing in this tree: 220 221 | 222 | * Commit A2, on branch "feature" (HEAD) 223 | | 224 | | * Commit B1, on branch "subfeature" 225 | |/ 226 | * Commit A1, on branch "feature" 227 |/ 228 * Commit M1, on branch "master" 229 | 230 231 This tree represents making another commit (`A2`) on "feature", on top of `A1`. 232 233 Here, when `arc diff` is run from branch "feature" (with HEAD at `A2`), this 234 rule will incorrectly select only `A2` because `A2` (which is HEAD) appears on 235 one branch ("feature") while `A1` appears on two branches ("feature", 236 "subfeature"). 237 238 You can avoid this problem by amending changes into `A1` instead of adding new 239 commits, or by rebasing "subfeature" before running `arc diff`. 240 241 This rule will also select the wrong commit range in a tree like this: 242 243 | 244 | * Commit A1', on branch "feature", created by amending A1 245 | | 246 | | * Commit B1, on branch "subfeature" (HEAD) 247 | |/ 248 | o Commit A1, no longer on "feature" but still on "subfeature" 249 |/ 250 * Commit M1, on branch "master" 251 | 252 253 This tree represents amending `A1` without rebasing "subfeature", so that `A1` 254 is no longer on "feature" (replaced with `A1'`) but still on "subfeature". In 255 this case, running `arc diff` from "subfeature" will incorrectly select both 256 `B1` and `A1`, because they now are contained by the same number of branches. 257 258 You can avoid this problem by rebasing sub-branches before running `arc diff`, 259 or by using a rule like `arc:amended` before `git:branch-unique(*)`. 260 261 == arc:bookmark == 262 263 This rule only works in Mercurial. 264 265 This rule finds outgoing changes, but stops when it encounters a bookmark. It is 266 most likely to be useful if you use one bookmark per feature. 267 268 This rule operates like `arc:outgoing`, but then walks the commits between 269 `.` and the selected base commit. It stops when it encounters a bookmark. For 270 example, if you have a tree like this: 271 272 | 273 | * C4 (outgoing, bookmark: stripes) 274 | | 275 | * C3 (outgoing, bookmark: zebra) 276 | | 277 | * C2 (outgoing, no bookmark) 278 |/ 279 * C1 (pushed, no bookmark) 280 | 281 282 When run from `C4`, this rule will select just `C4`, stopping on `C3` because 283 it has a different bookmark. When run from `C3`, it will select `C2` and `C3`. 284 285 However, this rule will select the wrong commit range in some cases (for 286 example, if the "zebra" bookmark has moved on, the rule will no longer stop on 287 `C3` and will select `C2`, `C3` and `C4` when run from `C4`). 288 289 == arc:exec(*) == 290 291 This rule runs some external script or shell command. It is intended for 292 advanced users who want specialized behavior that can't be expressed with other 293 rules. 294 295 To use this rule, provide some script or shell command. For example: 296 297 arc:exec(git merge-base origin/master HEAD) 298 arc:exec(/path/to/some/script.sh) 299 300 The command will be executed with the working copy as its working directory, 301 and passed no arguments. To //match//, it should print the name of a base commit 302 on stdout and then exit with return code 0. To //fail//, it should exit with 303 any other return code. 304 305 = Next Steps = 306 307 Continue by: 308 309 - learning about `arc diff` in more detail with 310 @{article:Arcanist User Guide: arc diff}; or 311 - returning to @{article:Arcanist User Guide}.
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |