| 1 | --- |
| 2 | layout: reference |
| 3 | --- |
| 4 | |
| 5 | <div class="box"> |
| 6 | <h2> |
| 7 | <span class="docs"> |
| 8 | <a target="new" href="http://git-scm.com/book/en/Git-Basics-Viewing-the-Commit-History">book</a> |
| 9 | </span> |
| 10 | Inspection and Comparison |
| 11 | </h2> |
| 12 | <div class="block"> |
| 13 | <p> |
| 14 | So now you have a bunch of branches that you are using for short lived |
| 15 | topics, long lived features and what not. How do you keep track of them? |
| 16 | Git has a couple of tools to help you figure out where work was done, what |
| 17 | the difference between two branches are and more. |
| 18 | </p> |
| 19 | |
| 20 | <p class="nutshell"> |
| 21 | <b>In a nutshell</b> you can use <code>git log</code> to find specific |
| 22 | commits in your project history - by author, date, content or |
| 23 | history. You can use <code>git diff</code> to compare two different points |
| 24 | in your history - generally to see how two branches differ or what has |
| 25 | changed from one version of your software to another. |
| 26 | </p> |
| 27 | </div> |
| 28 | </div> |
| 29 | |
| 30 | <div class="box"> |
| 31 | <h2> |
| 32 | <span class="docs"> |
| 33 | <a target="new" href="http://git-scm.com/docs/git-log">docs</a> |
| 34 | <a target="new" href="http://git-scm.com/book/en/Git-Basics-Viewing-the-Commit-History#Limiting-Log-Output">book</a> |
| 35 | </span> |
| 36 | <a name="log">git log</a> |
| 37 | <span class="desc">filter your commit history</span> |
| 38 | </h2> |
| 39 | |
| 40 | <div class="block"> |
| 41 | <p>We've already seen how to use <code>git log</code> to compare branches, |
| 42 | by looking at the commits on one branch that are not reachable from another. |
| 43 | (If you don't remember, it looks like this: <code>git log branchA ^branchB</code>). |
| 44 | However, you can also use <code>git log</code> to look for specific commits. |
| 45 | Here we'll be looking at some of the more commonly used <code>git log</code> |
| 46 | options, but there are many. Take a look at the official docs for the whole |
| 47 | list. |
| 48 | </p> |
| 49 | |
| 50 | <h4 id="log-author"> |
| 51 | git log --author |
| 52 | <small>look for only commits from a specific author</small> |
| 53 | </h4> |
| 54 | |
| 55 | <p> |
| 56 | To filter your commit history to only the ones done by a specific author, |
| 57 | you can use the <code>--author</code> option. For example, let's say we're |
| 58 | looking for the commits in the Git source code done by Linus. We would |
| 59 | type something like <code>git log --author=Linus</code>. The search is |
| 60 | case sensitive and will also search the email address. The following |
| 61 | example will use the <code>-[number]</code> option, which will limit the |
| 62 | results to the last [number] commits. |
| 63 | </p> |
| 64 | |
| 65 | <pre> |
| 66 | <b>$ git log --author=Linus --oneline -5</b> |
| 67 | 81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory |
| 68 | 3bb7256 make "index-pack" a built-in |
| 69 | 377d027 make "git pack-redundant" a built-in |
| 70 | b532581 make "git unpack-file" a built-in |
| 71 | 112dd51 make "mktag" a built-in |
| 72 | </pre> |
| 73 | |
| 74 | <h4 id="log-date"> |
| 75 | git log --since --before |
| 76 | <small>filter commits by date committed</small> |
| 77 | </h4> |
| 78 | |
| 79 | <p> |
| 80 | If you want to specify a date range that you're interested in filtering your |
| 81 | commits down to, you can use a number of options such as <code>--since</code> |
| 82 | and <code>--before</code>, or you can also use <code>--until</code> and |
| 83 | <code>--after</code>. For example, to see all the commits in |
| 84 | the Git project before three weeks ago but after April 18th, you could run this |
| 85 | (We're also going to use <code>--no-merges</code> to remove merge commits): |
| 86 | </p> |
| 87 | |
| 88 | <pre> |
| 89 | <b>$ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges</b> |
| 90 | 5469e2d Git 1.7.1-rc2 |
| 91 | d43427d Documentation/remote-helpers: Fix typos and improve language |
| 92 | 272a36b Fixup: Second argument may be any arbitrary string |
| 93 | b6c8d2d Documentation/remote-helpers: Add invocation section |
| 94 | 5ce4f4e Documentation/urls: Rewrite to accomodate transport::address |
| 95 | 00b84e9 Documentation/remote-helpers: Rewrite description |
| 96 | 03aa87e Documentation: Describe other situations where -z affects git diff |
| 97 | 77bc694 rebase-interactive: silence warning when no commits rewritten |
| 98 | 636db2c t3301: add tests to use --format="%N" |
| 99 | </pre> |
| 100 | |
| 101 | <h4 id="log-grep"> |
| 102 | git log --grep |
| 103 | <small>filter commits by commit message</small> |
| 104 | </h4> |
| 105 | |
| 106 | <p> |
| 107 | You may also want to look for commits with a certain phrase in the commit |
| 108 | message. Use <code>--grep</code> for that. Let's say there |
| 109 | was a commit that dealt with using the P4EDITOR environment variable and |
| 110 | you wanted to remember what that change looked like - you could find the commit |
| 111 | with <code>--grep</code>. |
| 112 | </p> |
| 113 | |
| 114 | <pre> |
| 115 | <b>$ git log --grep=P4EDITOR --no-merges</b> |
| 116 | <span class="yellow">commit 82cea9ffb1c4677155e3e2996d76542502611370</span> |
| 117 | Author: Shawn Bohrer |
| 118 | Date: Wed Mar 12 19:03:24 2008 -0500 |
| 119 | |
| 120 | git-p4: Use P4EDITOR environment variable when set |
| 121 | |
| 122 | Perforce allows you to set the P4EDITOR environment variable to your |
| 123 | preferred editor for use in perforce. Since we are displaying a |
| 124 | perforce changelog to the user we should use it when it is defined. |
| 125 | |
| 126 | Signed-off-by: Shawn Bohrer <shawn.bohrer@gmail.com> |
| 127 | Signed-off-by: Simon Hausmann <simon@lst.de> |
| 128 | </pre> |
| 129 | |
| 130 | <p> |
| 131 | Git will logically OR all <code>--grep</code> and <code>--author</code> |
| 132 | arguments. If you want to use <code>--grep</code> and <code>--author</code> |
| 133 | to see commits that were authored by someone AND have a specific message |
| 134 | content, you have to add the <code>--all-match</code> option. In these |
| 135 | examples we're going to use the <code>--format</code> option, so we can see |
| 136 | who the author of each commit was. |
| 137 | </p> |
| 138 | |
| 139 | <p>If we look for the commit messages with 'p4 depo' in them, we get these |
| 140 | three commits:</p> |
| 141 | |
| 142 | <pre> |
| 143 | <b>$ git log --grep="p4 depo" --format="%h %an %s"</b> |
| 144 | ee4fd1a Junio C Hamano Merge branch 'master' of git://repo.or.cz/git/fastimport |
| 145 | da4a660 Benjamin Sergeant git-p4 fails when cloning a p4 depo. |
| 146 | 1cd5738 Simon Hausmann Make incremental imports easier to use by storing the p4 d |
| 147 | </pre> |
| 148 | |
| 149 | <p>If we add a <code>--author=Hausmann</code> argument, instead of further |
| 150 | filtering it down to the one commit by Simon, it instead will show all |
| 151 | commits by Simon OR commits with "p4 depo" in the message:</p> |
| 152 | |
| 153 | <pre> |
| 154 | <b>$ git log --grep="p4 depo" --format="%h %an %s" --author="Hausmann"</b> |
| 155 | cdc7e38 Simon Hausmann Make it possible to abort the submission of a change to Pe |
| 156 | f5f7e4a Simon Hausmann Clean up the git-p4 documentation |
| 157 | 30b5940 Simon Hausmann git-p4: Fix import of changesets with file deletions |
| 158 | 4c750c0 Simon Hausmann git-p4: git-p4 submit cleanups. |
| 159 | 0e36f2d Simon Hausmann git-p4: Removed git-p4 submit --direct. |
| 160 | edae1e2 Simon Hausmann git-p4: Clean up git-p4 submit's log message handling. |
| 161 | 4b61b5c Simon Hausmann git-p4: Remove --log-substitutions feature. |
| 162 | 36ee4ee Simon Hausmann git-p4: Ensure the working directory and the index are cle |
| 163 | e96e400 Simon Hausmann git-p4: Fix submit user-interface. |
| 164 | 38f9f5e Simon Hausmann git-p4: Fix direct import from perforce after fetching cha |
| 165 | 2094714 Simon Hausmann git-p4: When skipping a patch as part of "git-p4 submit" m |
| 166 | 1ca3d71 Simon Hausmann git-p4: Added support for automatically importing newly ap |
| 167 | ... |
| 168 | </pre> |
| 169 | |
| 170 | <p>However, adding <code>--all-match</code> will get the results you're |
| 171 | looking for:</p> |
| 172 | |
| 173 | <pre> |
| 174 | <b>$ git log --grep="p4 depo" --format="%h %an %s" --author="Hausmann" --all-match</b> |
| 175 | 1cd5738 Simon Hausmann Make incremental imports easier to use by storing the p4 d |
| 176 | </pre> |
| 177 | |
| 178 | <h4 id="log-s"> |
| 179 | git log -S |
| 180 | <small>filter by introduced diff</small> |
| 181 | </h4> |
| 182 | |
| 183 | <p> |
| 184 | What if you write really horrible commit messages? Or, what if you are |
| 185 | looking for when a function was introduced, or where variables started |
| 186 | to be used? You can also tell Git to look through the diff of each |
| 187 | commit for a string. For example, if we wanted to find which commits |
| 188 | modified anything that looked like the function name |
| 189 | 'userformat_find_requirements', we would run this: (note there is no '=' |
| 190 | between the '-S' and what you are searching for) |
| 191 | </p> |
| 192 | |
| 193 | <pre> |
| 194 | <b>$ git log -Suserformat_find_requirements</b> |
| 195 | <span class="yellow">commit 5b16360330822527eac1fa84131d185ff784c9fb</span> |
| 196 | Author: Johannes Gilger |
| 197 | Date: Tue Apr 13 22:31:12 2010 +0200 |
| 198 | |
| 199 | pretty: Initialize notes if %N is used |
| 200 | |
| 201 | When using git log --pretty='%N' without an explicit --show-notes, git |
| 202 | would segfault. This patches fixes this behaviour by loading the needed |
| 203 | notes datastructures if --pretty is used and the format contains %N. |
| 204 | When --pretty='%N' is used together with --no-notes, %N won't be |
| 205 | expanded. |
| 206 | |
| 207 | This is an extension to a proposed patch by Jeff King. |
| 208 | |
| 209 | Signed-off-by: Johannes Gilger |
| 210 | Signed-off-by: Junio C Hamano |
| 211 | </pre> |
| 212 | |
| 213 | <h4 id="log-patch"> |
| 214 | git log -p |
| 215 | <small>show patch introduced at each commit</small> |
| 216 | </h4> |
| 217 | |
| 218 | <p> |
| 219 | Each commit is a snapshot of the project, but since each commit records the |
| 220 | snapshot it was based off of, Git can always calculate the difference and |
| 221 | show it to you as a patch. That means for any commit you can get the patch |
| 222 | that commit introduced to the project. You can either do this by running |
| 223 | <code>git show [SHA]</code> with a specific commit SHA, or you can run |
| 224 | <code>git log -p</code>, which tells Git to put the patch after each commit. |
| 225 | It is a great way to summarize what has happened on a branch or between |
| 226 | commits. |
| 227 | </p> |
| 228 | |
| 229 | <pre> |
| 230 | <b>$ git log -p --no-merges -2</b> |
| 231 | <span class="yellow">commit 594f90bdee4faf063ad07a4a6f503fdead3ef606</span> |
| 232 | Author: Scott Chacon <schacon@gmail.com> |
| 233 | Date: Fri Jun 4 15:46:55 2010 +0200 |
| 234 | |
| 235 | reverted to old class name |
| 236 | |
| 237 | <span class="umber">diff --git a/ruby.rb b/ruby.rb |
| 238 | index bb86f00..192151c 100644 |
| 239 | --- a/ruby.rb |
| 240 | +++ b/ruby.rb</span> |
| 241 | <span class="lblue">@@ -1,7 +1,7 @@</span> |
| 242 | <span class="red">-class HiWorld</span> |
| 243 | <span class="green">+class HelloWorld</span> |
| 244 | def self.hello |
| 245 | puts "Hello World from Ruby" |
| 246 | end |
| 247 | end |
| 248 | |
| 249 | <span class="red">-HiWorld.hello</span> |
| 250 | <span class="green">+HelloWorld.hello</span> |
| 251 | |
| 252 | <span class="yellow">commit 3cbb6aae5c0cbd711c098e113ae436801371c95e</span> |
| 253 | Author: Scott Chacon <schacon@gmail.com> |
| 254 | Date: Fri Jun 4 12:58:53 2010 +0200 |
| 255 | |
| 256 | fixed readme title differently |
| 257 | |
| 258 | <span class="umber">diff --git a/README b/README |
| 259 | index d053cc8..9103e27 100644 |
| 260 | --- a/README |
| 261 | +++ b/README</span> |
| 262 | <span class="lblue">@@ -1,4 +1,4 @@</span> |
| 263 | <span class="red">-Hello World Examples</span> |
| 264 | <span class="green">+Many Hello World Examples</span> |
| 265 | ====================== |
| 266 | |
| 267 | This project has examples of hello world in |
| 268 | </pre> |
| 269 | |
| 270 | <p>This is a really nice way of summarizing changes or reviewing a series |
| 271 | of commits before merging them or releasing something.</p> |
| 272 | |
| 273 | <h4 id="log-stat"> |
| 274 | git log --stat |
| 275 | <small>show diffstat of changes introduced at each commit</small> |
| 276 | </h4> |
| 277 | |
| 278 | <p>If the <code>-p</code> option is too verbose for you, you can summarize |
| 279 | the changes with <code>--stat</code> instead. Here is the same log output |
| 280 | with <code>--stat</code> instead of <code>-p</code></p> |
| 281 | |
| 282 | <pre> |
| 283 | <b>$ git log --stat --no-merges -2</b> |
| 284 | <span class="yellow">commit 594f90bdee4faf063ad07a4a6f503fdead3ef606</span> |
| 285 | Author: Scott Chacon <schacon@gmail.com> |
| 286 | Date: Fri Jun 4 15:46:55 2010 +0200 |
| 287 | |
| 288 | reverted to old class name |
| 289 | |
| 290 | ruby.rb | 4 <span class="green">++</span><span class="red">--</span> |
| 291 | 1 files changed, 2 insertions(+), 2 deletions(-) |
| 292 | |
| 293 | <span class="yellow">commit 3cbb6aae5c0cbd711c098e113ae436801371c95e</span> |
| 294 | Author: Scott Chacon <schacon@gmail.com> |
| 295 | Date: Fri Jun 4 12:58:53 2010 +0200 |
| 296 | |
| 297 | fixed readme title differently |
| 298 | |
| 299 | README | 2 <span class="green">+</span><span class="red">-</span> |
| 300 | 1 files changed, 1 insertions(+), 1 deletions(-) |
| 301 | </pre> |
| 302 | |
| 303 | <p>Same basic information, but a little more compact - it still lets you |
| 304 | see relative changes and which files were modified.</p> |
| 305 | |
| 306 | </div> |
| 307 | </div> |
| 308 | |
| 309 | <div class="box"> |
| 310 | <h2> |
| 311 | <span class="docs"> |
| 312 | <a target="new" href="http://git-scm.com/docs/git-diff">docs</a> |
| 313 | <a target="new" href="http://git-scm.com/book/en/Distributed-Git-Maintaining-a-Project#Determining-What-Is-Introduced">book</a> |
| 314 | </span> |
| 315 | <a name="diff">git diff</a> |
| 316 | <span class="desc"></span> |
| 317 | </h2> |
| 318 | |
| 319 | <div class="block"> |
| 320 | |
| 321 | <p>Finally, to see the absolute changes between any two commit snapshots, |
| 322 | you can use the <code>git diff</code> command. This is largely used in two |
| 323 | main situations - seeing how two branches differ from one another and |
| 324 | seeing what has changed since a release or some other older point in |
| 325 | history. Let's look at both of these situations.</p> |
| 326 | |
| 327 | <p>To see what has changed since the last release, you can simply run |
| 328 | <code>git diff [version]</code> (or whatever you tagged the release). |
| 329 | For example, if we want to see what has changed in our project since |
| 330 | the v0.9 release, we can run <code>git diff v0.9</code>. |
| 331 | </p> |
| 332 | |
| 333 | <pre> |
| 334 | <b>$ git diff v0.9</b> |
| 335 | <span class="umber">diff --git a/README b/README |
| 336 | index d053cc8..d4173d5 100644 |
| 337 | --- a/README |
| 338 | +++ b/README</span> |
| 339 | <span class="lblue">@@ -1,4 +1,4 @@</span> |
| 340 | <span class="red">-Hello World Examples</span> |
| 341 | <span class="green">+Many Hello World Lang Examples</span> |
| 342 | ====================== |
| 343 | |
| 344 | This project has examples of hello world in |
| 345 | <span class="umber">diff --git a/ruby.rb b/ruby.rb |
| 346 | index bb86f00..192151c 100644 |
| 347 | --- a/ruby.rb |
| 348 | +++ b/ruby.rb</span> |
| 349 | <span class="lblue">@@ -1,7 +1,7 @@</span> |
| 350 | <span class="red">-class HiWorld</span> |
| 351 | <span class="green">+class HelloWorld</span> |
| 352 | def self.hello |
| 353 | puts "Hello World from Ruby" |
| 354 | end |
| 355 | end |
| 356 | |
| 357 | <span class="red">-HiWorld.hello</span> |
| 358 | <span class="green">+HelloWorld.hello</span> |
| 359 | </pre> |
| 360 | |
| 361 | <p>Just like <code>git log</code>, you can use the <code>--stat</code> |
| 362 | option with it.</p> |
| 363 | |
| 364 | <pre> |
| 365 | <b>$ git diff v0.9 --stat</b> |
| 366 | README | 2 +- |
| 367 | ruby.rb | 4 ++-- |
| 368 | 2 files changed, 3 insertions(+), 3 deletions(-) |
| 369 | </pre> |
| 370 | |
| 371 | <p>To compare two divergent branches, however, you can run something like |
| 372 | <code>git diff branchA branchB</code> but the problem is that it will do |
| 373 | exactly what you are asking - it will basically give you a patch file that |
| 374 | would turn the snapshot at the tip of branchA into the snapshot at the tip |
| 375 | of branchB. This means if the two branches have diverged - gone in different |
| 376 | directions - it will remove all the work that was introduced into branchA |
| 377 | and then add everything that was introduced into branchB. This is probably |
| 378 | not what you want - you want the changes added to branchB that are not in |
| 379 | branchA, so you really want the difference between where the two branches |
| 380 | diverged and the tip of branchB. So, if our history looks like this:</p> |
| 381 | |
| 382 | <pre> |
| 383 | <b>$ git log --graph --oneline --decorate --all</b> |
| 384 | * 594f90b (HEAD, tag: v1.0, master) reverted to old class name |
| 385 | | * 1834130 (erlang) added haskell |
| 386 | | * ab5ab4c added erlang |
| 387 | |/ |
| 388 | * 8d585ea Merge branch 'fix_readme' |
| 389 | ... |
| 390 | </pre> |
| 391 | |
| 392 | <p>And we want to see what is on the "erlang" branch compared to the "master" |
| 393 | branch, running <code>git diff master erlang</code> will give us the wrong |
| 394 | thing.</p> |
| 395 | |
| 396 | <pre> |
| 397 | <b>$ git diff --stat master erlang</b> |
| 398 | erlang_hw.erl | 5 +++++ |
| 399 | haskell.hs | 4 ++++ |
| 400 | ruby.rb | 4 ++-- |
| 401 | 3 files changed, 11 insertions(+), 2 deletions(-) |
| 402 | </pre> |
| 403 | |
| 404 | <p>You see that it adds the erlang and haskell files, which is what we did |
| 405 | in that branch, but then the output also reverts the changes to the ruby file |
| 406 | that we did in the master branch. What we really want to see is just the |
| 407 | changes that happened in the "erlang" branch (adding the two files). We can |
| 408 | get the desired result by doing the diff from the common commit they diverged |
| 409 | from:</p> |
| 410 | |
| 411 | <pre> |
| 412 | <b>$ git diff --stat 8d585ea erlang</b> |
| 413 | erlang_hw.erl | 5 +++++ |
| 414 | haskell.hs | 4 ++++ |
| 415 | 2 files changed, 9 insertions(+), 0 deletions(-) |
| 416 | </pre> |
| 417 | |
| 418 | <p>That's what we're looking for, but we don't want to have to figure out |
| 419 | what commit the two branches diverged from every time. Luckily, Git has a |
| 420 | shortcut for this. If you run <code>git diff master...erlang</code> (with |
| 421 | three dots in between the branch names), Git will automatically figure out |
| 422 | what the common commit (otherwise known as the "merge base") of the two |
| 423 | commit is and do the diff off of that.</p> |
| 424 | |
| 425 | <pre> |
| 426 | <b>$ git diff --stat master erlang</b> |
| 427 | erlang_hw.erl | 5 +++++ |
| 428 | haskell.hs | 4 ++++ |
| 429 | ruby.rb | 4 ++-- |
| 430 | 3 files changed, 11 insertions(+), 2 deletions(-) |
| 431 | <b>$ git diff --stat master...erlang</b> |
| 432 | erlang_hw.erl | 5 +++++ |
| 433 | haskell.hs | 4 ++++ |
| 434 | 2 files changed, 9 insertions(+), 0 deletions(-) |
| 435 | </pre> |
| 436 | |
| 437 | <p>Nearly every time you want to compare two branches, you'll want to use |
| 438 | the triple-dot syntax, because it will almost always give you what you want. |
| 439 | </p> |
| 440 | |
| 441 | <p>As a bit of an aside, you can also have Git manually calculate what the |
| 442 | merge-base (first common ancestor commit) of any two commits would be with |
| 443 | the <code>git merge-base</code> command:</p> |
| 444 | |
| 445 | <pre> |
| 446 | <b>$ git merge-base master erlang</b> |
| 447 | 8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d |
| 448 | </pre> |
| 449 | |
| 450 | <p>You can do the equivalent of <code>git diff master...erlang</code> |
| 451 | by running this:</p> |
| 452 | |
| 453 | <pre> |
| 454 | <b>$ git diff --stat $(git merge-base master erlang) erlang</b> |
| 455 | erlang_hw.erl | 5 +++++ |
| 456 | haskell.hs | 4 ++++ |
| 457 | 2 files changed, 9 insertions(+), 0 deletions(-) |
| 458 | </pre> |
| 459 | |
| 460 | <p>You may prefer using the easier syntax though.</p> |
| 461 | |
| 462 | |
| 463 | <p class="nutshell"> |
| 464 | <b>In a nutshell</b> you can use <code>git diff</code> to see how a project |
| 465 | has changed since a known point in the past or to see what unique work is |
| 466 | in one branch since it diverged from another. Always use |
| 467 | <code>git diff branchA...branchB</code> to inspect branchB relative to |
| 468 | branchA to make things easier. |
| 469 | </p> |
| 470 | |
| 471 | </div> |
| 472 | </div> |
| 473 | |
| 474 | <p>And that's it! For more information, try reading the |
| 475 | <a href="http://git-scm.com/book/">Pro Git book</a>.</p> |