You are on page 1of 415

Smacking Git Around

by Scott Chacon

Me

Scott Chacon

github.com/schacon

“Scott Chacon has an understandable but borderline unhealthy obsession with Git”
- Ilya Grigorik igvita.com

git-scm.com

book.git-scm.com

schacon@gmail.com

</me>

previously, on Git...

GIT

Git

image by matthew mccullough

Scott

Scott Chacon

Scott Chacon is a Git

v1

v2

v3

98ca9.. commit
tree author committer

34ac2.. commit
tree parent author committer

f30ab.. commit
tree parent author committer

size
0de24 Scott Scott

size
184ca 98ca9 Scott Scott

size
92ec2 34ac2 Scott Scott

initial commit of my project

fixed bug #1328 - stack overflow under certain

add feature #32 - ability to add new formats to the central

snapshot A

snapshot B

snapshot C

98ca9.. commit
tree parent author committer
nil Scott Scott

size
0de24

e8455..

0de24.. 0de24..
tree
blob tree

blob
== LICENSE: (The MIT License)

size

size
e8455 README 10af9 lib

Copyright (c) 2007 Tom PrestonPermission is hereby granted, f ree of charge, to any person ob

my commit message goes here and it is really, really cool

10af9.. tree
blob tree

bc52a.. size blob
require 'grit/index' require 'grit/status'

size

bc52a mylib.rb b70f8 inc

module Grit class << self attr_accessor :debug

b70f8.. tree
blob

size
0ad1a tricks.rb

0ad1a.. blob size
require 'grit/git-ruby/reposi require 'grit/git-ruby/file_i module Grit module Tricks

98ca9.. commit
tree parent author committer
nil Scott Scott

size
0de24

e8455..

0de24.. 0de24..
tree
blob tree

blob
== LICENSE: (The MIT License)

size

size
e8455 README 10af9 lib

Copyright (c) 2007 Tom PrestonPermission is hereby granted, f ree of charge, to any person ob

my commit message goes here and it is really, really cool

10af9.. tree
blob tree

bc52a.. size blob
require 'grit/index' require 'grit/status'

size

bc52a mylib.rb b70f8 inc

module Grit class << self attr_accessor :debug

b70f8.. tree
blob

size
0ad1a tricks.rb

0ad1a.. blob size
require 'grit/git-ruby/reposi require 'grit/git-ruby/file_i module Grit module Tricks

0de24.. 22d8858e8513666bf91b82bd2939ec7b0d1974da

stable

master

98ca9

34ac2

f30ab

a23fe

3acd1

topic

stable

master

98ca9

34ac2

f30ab

a23fe

3acd1

topic

stable

master

98ca9

34ac2

f30ab

a23fe

3acd1

topic

stable

master

98ca9

34ac2

f30ab

a23fe

3acd1

topic

$ time git checkout -b newbranch Switched to a new branch "newbranch" real 0m0.040s user 0m0.003s sys 0m0.008s

$ time git checkout -b newbranch Switched to a new branch "newbranch" real 0m0.040s user 0m0.003s sys 0m0.008s

master

develop

topic

distributed development

image by matthew mccullough

ccf03da00eca1b60a489354c1278c27f1fbc55dc a640106f173c5be59ed5757cf33f568b3e10994f c51a137df64b8ed2f8d84ad62df7b49b1c409906 7e06f7f8d471d5ccbe958fcfaef0fc48ff1a3def dafe95908f7b9cbd2697f04544b68904a6c59aac 2934b685f5dfd2b12c5d7d35d07c6058640f0581 d3b47a90ef9bf2d7bbc5a7cf2b2f27eef4a08f04 dbfeee0f5717d9978788da17cd6853316c92744a 864734938d4044fc5e713e4818f60ecb4f460525 3793a0108438a539f958236dbb9f4ea98b6b70ea 00a60fa1439f082128c1ec03ec3c73acab074d31 6ba82b4879f04de35ffe2ef02d50df0adf184fad 861020b6afeeec245afa2f864c72f5c2588295be 505f3128a573bfe1d23aec2acef83c34c3cbd8be 213e6f8761df038ab0b7c34a9fc4c2c3ce6c8b43 798a8088bcc7cf47fdb33a9d79e398220b660f88

C

fast

efficient

100k repos

80k users

</git-recap>

Git Tips and Tricks

Tips and Tricks
Selection and Ranges Data Munging Debugging Customizing

Selection and Ranges

Revision Selection

Revision Selection
alternate ways to refer to objects or ranges of objects

Revision Selection
full sha-1 partial sha-1 branch or tag name caret parent tilde spec blob spec relative specs ranges

Full SHA1
6e453f523fa1da50ecb04431101112b3611c6a4d

Partial SHA1
6e453f523fa1da50ecb04431101112b3611c6a4d 6e453f523fa1da50 6e453

Branch, Remote or Tag Name
v1.0 default m/cupcake

Caret Parent
default^2
2nd parent of ‘default’

b3be1

a09c6

df2fa

c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

master^
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

master^2
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

Tilde Spec
default~2
grandparent of ‘default’ (parent of the parent)

master~2
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

master^^^2 master~2^2
b3be1 a09c6 df2fa c36ae 5ec47 ce0e4 2f45e 4eadf 2fbb3 18cae

jess/master

master

master^^^2 master~2^2
b3be1 a09c6 df2fa c36ae 5ec47 ce0e4 2f45e 4eadf 2fbb3 18cae

jess/master

master

master^^^2 master~2^2
b3be1 a09c6 df2fa c36ae 5ec47 ce0e4 2f45e 4eadf 2fbb3 18cae

jess/master

master

Blob Spec
default:path/to/file
blob of that file in ‘default’ commit

Relative Specs
master@{yesterday}
the commit ‘master’ was at yesterday

Relative Specs
master@{5}
the 5th prior value of ‘master’ (locally)

Ranges

Ranges
ce0e4..e4272
every commit reachable by e4272 that is not reachable by ce034

Ranges
[old]..[new]
every commit reachable by [new] that is not reachable by [old]

Ranges
ce0e4..
everything since a commit

“Reachability”

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..master
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..c36ae
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..c36ae
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..c36ae
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

jess/master..c36ae
b3be1 a09c6 df2fa c36ae

5ec47

ce0e4

2f45e

4eadf

2fbb3

18cae

jess/master

master

Advanced Log

Log Subsets

what am I going to push?

git log origin/master..

origin/master

C1

master

HEAD

C0

C4

master

HEAD

C3

C2

origin/master

C1

C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git fetch origin
C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log origin/master..
C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log origin/master..HEAD
C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log origin/master..HEAD
C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log origin/master..HEAD
C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log origin/master..HEAD
C0

commit 72d404debaa804fca82fd9cf710fbde48c7305c6 Author: Shawn O. Pearce <spearce@spearce.org> Date: Sun Oct 12 13:13:59 2008 -0700 test-lib: fix broken printf b8eecafd888d219633f4c29e8b6a90fc21a46dfd introduced usage of printf without a format string. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> commit 969c877506cf8cc760c7b251fef6c5b6850bfc19 Author: Jeff King <peff@peff.net> Date: Sun Oct 12 00:06:11 2008 -0400 git apply --directory broken for new files We carefully verify that the input to git-apply is sane, including cross-checking that the filenames we see in "+++" headers match what was provided on the command line of "diff --git". When --directory is used, however, we ended up comparing the unadorned name to one with the prepended root, causing us to complain about a mismatch. We simply need to prepend the root directory, if any, when pulling the name out of the git header. commit ff74126c03a8dfd04e7533573a5c420f2a7112ac Author: Johannes Schindelin <Johannes.Schindelin@gmx.de> Date: Fri Oct 10 13:42:12 2008 +0200 rebase -i: do not fail when there is no commit to cherry-pick

C4

commit 72d404debaa804fca82fd9cf710fbde48c7305c6 Author: Shawn O. Pearce <spearce@spearce.org> Date: Sun Oct 12 13:13:59 2008 -0700 test-lib: fix broken printf b8eecafd888d219633f4c29e8b6a90fc21a46dfd introduced usage of printf without a format string. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

C3

commit 969c877506cf8cc760c7b251fef6c5b6850bfc19 Author: Jeff King <peff@peff.net> Date: Sun Oct 12 00:06:11 2008 -0400 git apply --directory broken for new files We carefully verify that the input to git-apply is sane, including cross-checking that the filenames we see in "+++" headers match what was provided on the command line of "diff --git". When --directory is used, however, we ended up comparing the unadorned name to one with the prepended root, causing us to complain about a mismatch. We simply need to prepend the root directory, if any, when pulling the name out of the git header.

C2

commit ff74126c03a8dfd04e7533573a5c420f2a7112ac Author: Johannes Schindelin <Johannes.Schindelin@gmx.de> Date: Fri Oct 10 13:42:12 2008 +0200 rebase -i: do not fail when there is no commit to cherry-pick

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log
origin/master .. HEAD

C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log
HEAD .. origin/master

C0

origin/master

C7

C4

master

HEAD

C6

C3

C5

C2

C1

git log
HEAD .. origin/master

C0

“commits in origin/master not in HEAD”

git log origin/master.. git log origin/master..HEAD git log origin/master..master git log master ^origin/master git log master --not origin/master

git log HEAD ^origin/master

git log HEAD ^origin/master

git log master topic1 ^origin/master

origin/master

C1

C0

master

origin/master

C3

C1

C0

experiment

C10

C9

C8
master

origin/master

C3

C1

C0

experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

which changes aren’t in experiment?

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log origin/master master ^experiment
experiment

C10
origin/master master

C7

C5

C9

C6

C4

C8

C2

C3

C1

C0

git log --graph

git log --pretty=oneline --graph

gitk

gitk 6d13f..41aba

Revision Diffs

git diff revA revB

$ echo ‘version one’ > test $ git add test $ git commit -m ‘C1’

master

C1

$ git checkout -b topic $ echo ‘version two’ >> test $ git commit -m ‘C2’

topic

C2
master

C1

$ echo ‘version three’ >> test $ git commit -m ‘C3’
topic

C3

C2
master

C1

$ git checkout master $ echo ‘version four’ >> test $ git commit -m ‘C4’
topic

master

C3

C4

C2

C1

$ echo ‘version five’ >> test $ git commit -m ‘C5’
master topic

C5

C3

C4

C2

C1

master

topic

C5

C3

$ git diff topic

C4

C2

C1

master

topic

C5

what does topic have $ git diff that I don’t have?
C3 C2

topic

C4

C1

master

topic

C5

what would happen if I $ git diff topic merged in topic?
C3 C2

C4

C1

master

topic

C5

how do I make topic $ git diff look like HEAD?
C3 C2

topic

C4

C1

$ git diff topic
master topic

C5

C3

C4

C2

diff --git a/test b/test index 304313d..bd8c6c9 100644 --- a/test +++ b/test @@ -1,3 +1,3 @@ version one -version two -version three +version four +version five

C1

$ git diff topic
master topic

C5

C3

C4

C2

diff --git a/test b/test index 304313d..bd8c6c9 100644 --- a/test +++ b/test @@ -1,3 +1,3 @@ version one -version two -version three +version four +version five

C1

$ git diff HEAD topic
master topic

C5

C3

C4

C2

diff --git a/test b/test index bd8c6c9..304313d 100644 --- a/test +++ b/test @@ -1,3 +1,3 @@ version one -version four -version five +version two +version three

C1

$ git diff HEAD topic
master topic

C5

C3

C4

C2

diff --git a/test b/test index bd8c6c9..304313d 100644 --- a/test +++ b/test @@ -1,3 +1,3 @@ version one -version four -version five +version two +version three

C1

git diff HEAD

topic

git diff HEAD...topic

git diff HEAD...topic

$ git diff HEAD
master topic

topic

C5

C3

C4

C2

C1

$ git diff HEAD
master topic

topic

C5

C3

C4

C2

C1

$ git diff HEAD...topic
master topic

C5

C3

C4

C2

C1

$ git diff HEAD...topic
master topic

C5

C3

diff --git a/test b/test index 9bc69cf..304313d 100644 --- a/test +++ b/test @@ -1 +1,3 @@ version one +version two +version three

C4

C2

C1

$ git diff HEAD...topic
master topic

C5

what would happen if I merged in topic?
C3 C2

diff --git a/test b/test index 9bc69cf..304313d 100644 --- a/test +++ b/test @@ -1 +1,3 @@ version one +version two +version three

C4

C1

Data Munging

Rewriting History

Modifying the last commit

git commit --amend

Rebasing

master

topic

C5

C3

C4

C2

C1

topic

master

C6

C5

C3

C4

C2

C1

git merge master

master

topic

C5

C3

C4

C2

C1

git rebase master

master

topic

C5

C3

C4

C2

C1

git rebase master

master

topic

C5

C3

C4

C2

C1

git rebase master

master

topic

C5

C3

C4

C2

C1

git rebase master

master

topic

C5

C3

git diff c2 c3 > 2-3.patch

C4

C2

C1

git rebase master

master

topic

C5

C3

git diff c2 c3 > 2-3.patch
diff --git a/test b/test index 2eadcec..bd8c6c9 100644 --- a/test +++ b/test @@ -1,2 +1,3 @@ version one version four +version five

C4

C2

C1

git rebase master

master

topic

C5

C3

C4

C2

C1

2-3.patch

master

topic

C5

C3

C4

C2

C1

git diff c1 c2 > 1-2.patch 2-3.patch

master

topic

C5

C3

C4

C2

C1

git diff c1 c2 > 1-2.patch 1-2.patch 2-3.patch

master

topic

C5

C3

C4

C2

C1

1-2.patch 2-3.patch

git rebase master

master

topic

C5

C3

C4

C2

C1

1-2.patch 2-3.patch

git rebase master
1-2.patch
master topic

C5

C3

C4

C2

C1

2-3.patch

git rebase master
topic

master

C2'

C5

C3

C4

C2

C1

2-3.patch

2-3.patch
topic

git rebase master

master

C2'

C5

C3

C4

C2

C1

topic

git rebase master

C3'

master

C2'

C5

C3

C4

C2

C1

topic

C3'

master

C2'

git rebase master
C5 C3

C4

C2

C1

topic

C3'

master

C2'

git rebase master
C5 C3

C4

C2

C1

topic

C3'

C2'

git rebase master
master

C5

C4

C1

Fun with Rebasing

rebase --onto

Transplanting Topic Branches

master

C1

C2

master

C1

C2

C3

server

master

C1

C2

C3

server

C8

C9

client

master

C1

C2

C3

C4

C10

server

C8

C9

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

move your ‘client’ branch work to your ‘master’ branch

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase master

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase master

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase master

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase master

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase server

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase server

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase server

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

git rebase server

client

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

git rebase --onto master server

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

git rebase --onto master server

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

git rebase --onto master server

master

C1

C2

C5

C6

C3

C4

C10

server

C8

C9

client

git rebase --onto master server

master master

client

C1 C1

C2

C5

C6 C6

C8' C8

C9' C9

C3

C4 C4

C10 C10

server server

C8 C8

C9 C9

client

master

client

C1

C2

C5

C6

C8'

C9'

C3

C4

C10

server

C8

C9

master

client

C1

C2

C5

C6

C8'

C9'

C3

C4

C10

server

C8

C9

git checkout server git rebase master

master

client

C1

C2

C5

C6

C8'

C9'

C3

C4

C10

server

C8

C9

git checkout server git rebase client

master

client

C1

C2

C5

C6

C8'

C9'

C3

C4

C10

server

C8

C9

git checkout server git rebase client

master

client client

C1

C2

C5

C6 C6

C8'

C9'

C3' C3

C4' C4

C10' C10

server

C8

C9

git checkout server git rebase client

master

client client

server

C1 C1

C2 C2

C5 C5

C6 C6

C8' C8'

C9' C9'

C3' C3'

C4'

C10'

git checkout server git rebase client

master

client

server

C1

C2

C5

C6

C8'

C9'

C3'

C4'

C10'

git checkout server git rebase client

transplant some of a topic branch

master

C0

C1

C2

C3

C4

C5

topic

master

C0

C1

C2

C3

C4

C5

topic

master

C0

C1

C2

C3

C4

C5

topic

git branch newtopic C3

master

C0

C1

C2

C3

C4

C5

newtopic

topic

git branch newtopic C3

master

C0

C1

C2

C3

C4

C5

newtopic

topic

git branch newtopic C3 git rebase --onto master newtopic

master

topic

C0

C1

C2

C4'

C5'

C3

C4

C5

newtopic

git branch newtopic C3 git rebase --onto master newtopic

Fixing a commit several back

git rebase -i
git rebase --interactive

default

C4

C3

C2

C1

C0

default

C4

C3

C2

C1

C0

default

C4

C3

default~2

C2

C1

C0

default

C4

C3

default~2

C2

C1

C0

git rebase -i default~2^

git rebase -i default~2^

git rebase -i default~2^

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

C2
C3 C4

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

edit 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

$ git rebase -i default~2^ Stopped at 969c877... git apply --directory broken for new files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue $_

$ git rebase -i default~2^ Stopped at 969c877... git apply --directory broken for new files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue $_

edit files git add git commit --amend git rebase --continue

$ git rebase -i default~2^ Stopped at 969c877... git apply --directory broken for new files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue $_

edit files git add git commit --amend git rebase --continue

$ git rebase -i default~2^ Stopped at 969c877... git apply --directory broken for new files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue $_

edit files git add git commit --amend git rebase --continue

$ git rebase -i default~2^ Stopped at 969c877... git apply --directory broken for new files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue $_

edit files git add git commit --amend git rebase --continue

default

C4

C4'

C3

C3'

C2

C2'

C1

C0

default

C4

C4'

C3

C3'

C2

C2'

C1

C0

default

C4

C4'

C3

C3'

C2

C2'

C1

C0

Squashing commits together

pick 969c877 git apply --directory broken for new files pick b75271d git diff <tree>{3,}: do not reverse order of args pick 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

pick 969c877 git apply --directory broken for new files squash b75271d git diff <tree>{3,}: do not reverse order of args squash 72d404d test-lib: fix broken printf # Rebase f285a2d..5c283eb onto f285a2d # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. # ~ ~ ~ ~ ~ "~/projects/git/.git/rebase-merge/git-rebase-todo" 14L, 472C

# This is a combination of 3 commits. # The first commit's message is: git apply --directory broken for new files # This is the 2nd commit message: git diff <tree>{3,}: do not reverse order of args # This is the 3rd commit message: test-lib: fix broken printf # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Jeff King <peff@peff.net> # # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: builtin-apply.c # modified: builtin-diff.c # modified: t/t4013-diff-various.sh # new file: t/t4013/diff.diff_master_master^_side # modified: t/t4128-apply-root.sh # modified: t/test-lib.sh # ~ ~ ".git/COMMIT_EDITMSG" 39L, 1454C

# This is a combination of 3 commits. # The first commit's message is: git apply --directory broken for new files # This is the 2nd commit message: git diff <tree>{3,}: do not reverse order of args # This is the 3rd commit message: test-lib: fix broken printf # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Jeff King <peff@peff.net> # # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: builtin-apply.c # modified: builtin-diff.c # modified: t/t4013-diff-various.sh # new file: t/t4013/diff.diff_master_master^_side # modified: t/t4128-apply-root.sh # modified: t/test-lib.sh # ~ ~ ".git/COMMIT_EDITMSG" 39L, 1454C

# This is a combination of 3 commits. # The first commit's message is: git apply --directory broken for new files # This is the 2nd commit message: git diff <tree>{3,}: do not reverse order of args # This is the 3rd commit message: test-lib: fix broken printf # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Jeff King <peff@peff.net> # # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: builtin-apply.c # modified: builtin-diff.c # modified: t/t4013-diff-various.sh # new file: t/t4013/diff.diff_master_master^_side # modified: t/t4128-apply-root.sh # modified: t/test-lib.sh # ~ ~ ".git/COMMIT_EDITMSG" 39L, 1454C

# This is a combination of 3 commits. # The first commit's message is: git apply --directory broken for new files # This is the 2nd commit message: git diff <tree>{3,}: do not reverse order of args # This is the 3rd commit message: test-lib: fix broken printf # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Jeff King <peff@peff.net> # # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: builtin-apply.c # modified: builtin-diff.c # modified: t/t4013-diff-various.sh # new file: t/t4013/diff.diff_master_master^_side # modified: t/t4128-apply-root.sh # modified: t/test-lib.sh # ~ ~ ".git/COMMIT_EDITMSG" 39L, 1454C

C4

C3
default

C2

C5

C1

C0

The Perils

scott

jessica

default

C1

C0

scott

jessica

default

C4

C3

default

scott/default

C2

C1

C1

C0

C0

scott

jessica

default

scott/default

default

C7

C7

C4

C6

C6

C3

C5

C5

C2

C1

C1

C0

C0

scott

jessica

default

scott/default default

C8

C7

C7

C4

C6

C6

C3

C5

C5

C2

C1

C1

C0

C0

scott

jessica

default

scott/default default

C8

C7

C7'

C7

C4

C6

C6'

C6

C3

C5

C5'

C5

C2

C1

C1

C0

C0

scott

jessica

default

default

scott/default

C8

C7

C7'

C7'

C7

C4

C6

C6'

C6'

C6

C3

C5

C5'

C5'

C5

C2

C1

C1

C0

C0

scott

jessica

default

C9

scott/default default

C8

C7

C7'

C7'

C7

C4

C6

C6'

C6'

C6

C3

C5

C5'

C5'

C5

C2

C1

C1

C0

C0

Filter Branch
History Revision on Steroids

remove all instances of a file from every commit

git filter-branch --tree-filter 'rm -f filename' HEAD

change your email in all commits

git filter-branch --env-filter "export GIT_AUTHOR_EMAIL=you@email.com" HEAD

git filter-branch --env-filter "export GIT_AUTHOR_EMAIL=you@email.com" origin/master..HEAD

Subtree Merging

Alternative to Submodules

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

master

C3

C2

C1

C0

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ ls README rack_app.rb $ git remote add rack_remote git@github.com:schacon/rack.git $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, do Resolving deltas: 100% (1952/1952), done. From git@github.com:schacon/rack * [new branch] master -> rack_remote/master $ git checkout -b rack_branch rack_remote/master Branch rack_branch set up to track remote branch refs/remotes Switched to a new branch "rack_branch" $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

master

C3

rack_branch

C2

C6

rack_remote/master

C1

C5

C0

C4

$ git checkout master $ ls README rack_app.rb $ git checkout rack_branch $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ git checkout master $ ls README rack_app.rb $ git checkout rack_branch $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ git checkout master $ ls README rack_app.rb $ git checkout rack_branch $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

$ git checkout master $ ls README rack_app.rb $ git checkout rack_branch $ ls AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test

checkout ‘rack’ into my project

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

$ git read-tree --prefix=rack/ -u rack_branch $ ls README rack rack_app.rb $ ls rack AUTHORS KNOWN-ISSUES Rakefile contrib lib COPYING README bin example test $ git add rack $ git commit -m 'added rack code' [master 0839fd8] added rack code 108 files changed, 10334 insertions(+), 0 dele create mode 100644 rack/AUTHORS create mode 100644 rack/COPYING ... create mode 100644 rack/test/testrequest.rb

edit a file in rack

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge --squash -s subtree --no-commit master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge --squash -s subtree --no-commit master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge --squash -s subtree --no-commit master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

submit the change back to rack

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge --squash -s subtree --no-commit master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

git merge -s subtree

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

$ vim rack/lib/rack.rb $ git commit -am 'added awesome to rack' [master b1b77ee] added awesome to rack 1 files changed, 1 insertions(+), 0 deletions(-) $ git checkout rack_branch $ git merge -s subtree --no-commit --squash master Squash commit -- not updating HEAD Automatic merge went well; stopped before committin $ git status # On branch rack_branch # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: lib/rack.rb #

git merge -s subtree --no-commit --squash master

git merge -s subtree --no-commit --squash master

really?

Tim Dysinger http://dysinger.net/2008/04/29/ replacing-braid-or-piston-for-git-with-40-lines-of-rake/

Tim Dysinger http://dysinger.net/2008/04/29/ replacing-braid-or-piston-for-git-with-40-lines-of-rake/

http://tinyurl.com/braidgit

Patch Staging

git add -p

$ git status # On branch master # Changed but not updated: # (use "git add <file>..." to update what wi # (use "git checkout -- <file>..." to discar # # modified: ticgit.gemspec # no changes added to commit (use "git add" and/

$ git status # On branch master # Changed but not updated: # (use "git add <file>..." to update what wi # (use "git checkout -- <file>..." to discar # # modified: ticgit.gemspec # no changes added to commit (use "git add" and/

$ git add -p diff --git a/ticgit.gemspec b/ticgit.gemspec index 9c32bd4..a44667b 100644 --- a/ticgit.gemspec +++ b/ticgit.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "ticgit" s.version = "0.3.5" + s.version = "0.3.6" s.date = "2008-05-10" s.author = "Scott Chacon" s.email = "schacon@gmail.com" Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y

$ git add -p diff --git a/ticgit.gemspec b/ticgit.gemspec index 9c32bd4..a44667b 100644 --- a/ticgit.gemspec +++ b/ticgit.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "ticgit" s.version = "0.3.5" + s.version = "0.3.6" s.date = "2008-05-10" s.author = "Scott Chacon" s.email = "schacon@gmail.com" Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y

$ git add -p diff --git a/ticgit.gemspec b/ticgit.gemspec index 9c32bd4..a44667b 100644 --- a/ticgit.gemspec +++ b/ticgit.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "ticgit" s.version = "0.3.5" + s.version = "0.3.6" s.date = "2008-05-10" s.author = "Scott Chacon" s.email = "schacon@gmail.com" Stage this hunk [y,n,a,d,/,j,J,g,e,?]?

$ git add -p diff --git a/ticgit.gemspec b/ticgit.gemspec index 9c32bd4..a44667b 100644 --- a/ticgit.gemspec +++ b/ticgit.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "ticgit" s.version = "0.3.5" + s.version = "0.3.6" s.date = "2008-05-10" s.author = "Scott Chacon" s.email = "schacon@gmail.com" Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y

@@ -9,9 +9,10 @@ Gem::Specification.new do |s| s.files = ["lib/ticgit/base.rb", "lib/ticgit/ "lib/ticgit/comment.rb", "lib/ticgit/ticket.rb", "lib/ ticgit.rb", "bin/ti", "bin/ticgitweb"] s.bindir = 'bin' s.executables << "ti" s.executables << "ticgitweb" s.executables = ["ti", "ticgitweb"] s.default_executable = %q{ti} s.homepage = "http://github/schacon/ticgit"

+ +

s.require_paths = ["lib", "bin"] + s.specification_version = 2 if s.respond_to? :specification_version= end Stage this hunk [y,n,a,d,/,K,g,s,e,?]?

@@ -9,9 +9,10 @@ Gem::Specification.new do |s| s.files = ["lib/ticgit/base.rb", "lib/ticgit/ "lib/ticgit/comment.rb", "lib/ticgit/ticket.rb", "lib/ ticgit.rb", "bin/ti", "bin/ticgitweb"] s.bindir = 'bin' s.executables << "ti" s.executables << "ticgitweb" s.executables = ["ti", "ticgitweb"] s.default_executable = %q{ti} s.homepage = "http://github/schacon/ticgit"

+ +

s.require_paths = ["lib", "bin"] + s.specification_version = 2 if s.respond_to? :specification_version= end Stage this hunk [y,n,a,d,/,K,g,s,e,?]?

@@ -9,9 +9,10 @@ Gem::Specification.new do |s| s.files = ["lib/ticgit/base.rb", "lib/ticgit/ "lib/ticgit/comment.rb", "lib/ticgit/ticket.rb", "lib/ ticgit.rb", "bin/ti", "bin/ticgitweb"] s.bindir = 'bin' s.executables << "ti" s.executables << "ticgitweb" s.executables = ["ti", "ticgitweb"] s.default_executable = %q{ti} s.homepage = "http://github/schacon/ticgit"

+ +

s.require_paths = ["lib", "bin"] + s.specification_version = 2 if s.respond_to? :specification_version= end Stage this hunk [y,n,a,d,/,K,g,s,e,?]? n

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ticgit.gemspec # # Changed but not updated: # (use "git add <file>..." to update what will be com # (use "git checkout -- <file>..." to discard changes # # modified: ticgit.gemspec #

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ticgit.gemspec # # Changed but not updated: # (use "git add <file>..." to update what will be com # (use "git checkout -- <file>..." to discard changes # # modified: ticgit.gemspec #

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ticgit.gemspec # # Changed but not updated: # (use "git add <file>..." to update what will be com # (use "git checkout -- <file>..." to discard changes # # modified: ticgit.gemspec #

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ticgit.gemspec # # Changed but not updated: # (use "git add <file>..." to update what will be com # (use "git checkout -- <file>..." to discard changes # # modified: ticgit.gemspec #

partially stage files

git add -p

Debugging

Annotation

git blame

git blame
ie: “what dumbass did this? oh, it was me...”

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame daemon.c
979e32fa 85023577 77cb17e9 49ba83fb f8ff0c06 85023577 85023577 695dffe2 695dffe2 695dffe2 695dffe2 415e7b87 415e7b87 415e7b87 415e7b87 9048fe1c f8ff0c06 1955fabf f8ff0c06 960deccb 1b1dd23f 3bd62c21 3bd62c21 73a7a656 49ba83fb 678dac6b d9edcbd6 dd467629 dd467629 dd467629 4ae95682 4ae95682 96f1e58f (Randal L. Schwartz (Junio C Hamano (Michal Ostrowski (Jon Loeliger (Petr Baudis (Junio C Hamano (Junio C Hamano (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Johannes Schindelin (Patrick Welche (Patrick Welche (Patrick Welche (Patrick Welche (Petr Baudis (Petr Baudis (Mark Wooding (Petr Baudis (H. Peter Anvin (Stephan Beyer (Stephen R. van den Berg (Stephen R. van den Berg (Jens Axboe (Jon Loeliger (Tilman Sauerbeck (Junio C Hamano (Jon Loeliger (Jon Loeliger (Jon Loeliger (H. Peter Anvin (H. Peter Anvin (David Rientjes 2005-10-25 2006-12-19 2006-01-10 2006-09-19 2005-09-22 2006-12-19 2006-12-19 2006-09-28 2006-09-28 2006-09-28 2006-09-28 2007-10-18 2007-10-18 2007-10-18 2007-10-18 2005-09-24 2005-09-22 2006-02-03 2005-09-22 2005-10-19 2008-07-13 2008-08-14 2008-08-14 2007-07-27 2006-09-19 2006-08-22 2006-09-07 2006-09-26 2006-09-26 2006-09-26 2005-09-26 2005-09-26 2006-08-15 16:29:09 14:34:12 21:12:17 20:31:51 11:25:28 14:34:12 14:34:12 12:00:35 12:00:35 12:00:35 12:00:35 18:17:39 18:17:39 18:17:39 18:17:39 16:13:01 11:25:28 20:27:04 11:25:28 14:27:01 15:36:15 20:02:20 20:02:20 14:00:29 20:31:51 19:37:41 01:40:04 09:47:43 09:47:43 09:47:43 19:10:55 19:10:55 10:23:48 -0700 -0800 -0500 -0500 +0200 -0800 -0800 +0200 +0200 +0200 +0200 +0100 +0100 +0100 +0100 +0200 +0200 +0000 +0200 -0700 +0200 +0200 +0200 -0700 -0500 +0200 -0700 -0500 -0500 -0500 -0700 -0700 -0700 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) #include #include #include #include "cache.h" "pkt-line.h" "exec_cmd.h" "interpolate.h" #include <syslog.h> #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif static int log_syslog; static int verbose; static int reuseaddr; static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [ " [--timeout=n] [--init-ti " [--strict-paths] [--base " [--user-path | --user-pa " [--interpolated-path=pat " [--reuseaddr] [--detach] " [--[enable|disable|allow " [--inetd | [--listen=hos " [--user=user " [directory...]"; /* List of acceptable pathname prefi static char **ok_paths;

git blame -C GITPackUpload.m

git blame -C GITPackUpload.m
f344f58d f344f58d f344f58d f344f58d ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 a2cbabf5 ad11ac80 a2cbabf5 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 f344f58d f344f58d f344f58d f344f58d f344f58d 56ef2caf f344f58d Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-25 2009-03-24 2009-03-25 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-05 2009-01-04 18:59:04 18:59:04 18:59:04 18:59:04 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 22:29:39 18:32:50 22:29:39 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:59:04 18:59:04 18:59:04 18:59:04 18:59:04 21:44:26 18:59:04 -0800 -0800 -0800 -0800 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 -0800 -0800 -0800 -0800 -0800 -0800 -0800 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) 34) 35) 36) 37) 38) #define PACK_SIGN #define PACK_VERS @implementation G @synthesize @synthesize @synthesize @synthesize gitRe needR gitSo refDi

- (id) initWithGi { gitRepo = needRefs = gitSocket return sel } - (bool) uploadPa { NSLog(@"up NSString * NSArray *t refDict =

git blame -C GITPackUpload.m
f344f58d f344f58d f344f58d f344f58d ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 a2cbabf5 ad11ac80 a2cbabf5 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 f344f58d f344f58d f344f58d f344f58d f344f58d 56ef2caf f344f58d Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-25 2009-03-24 2009-03-25 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-05 2009-01-04 18:59:04 18:59:04 18:59:04 18:59:04 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 22:29:39 18:32:50 22:29:39 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:59:04 18:59:04 18:59:04 18:59:04 18:59:04 21:44:26 18:59:04 -0800 -0800 -0800 -0800 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 -0800 -0800 -0800 -0800 -0800 -0800 -0800 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) 34) 35) 36) 37) 38) #define PACK_SIGN #define PACK_VERS @implementation G @synthesize @synthesize @synthesize @synthesize gitRe needR gitSo refDi

- (id) initWithGi { gitRepo = needRefs = gitSocket return sel } - (bool) uploadPa { NSLog(@"up NSString * NSArray *t refDict =

git blame -C GITPackUpload.m
f344f58d f344f58d f344f58d f344f58d ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 a2cbabf5 ad11ac80 a2cbabf5 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 ad11ac80 f344f58d f344f58d f344f58d f344f58d f344f58d 56ef2caf f344f58d Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITPackUpload.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m Source/Network/GITServerHandler.m (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott (Scott Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon Chacon 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-25 2009-03-24 2009-03-25 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-03-24 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-04 2009-01-05 2009-01-04 18:59:04 18:59:04 18:59:04 18:59:04 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 22:29:39 18:32:50 22:29:39 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:32:50 18:59:04 18:59:04 18:59:04 18:59:04 18:59:04 21:44:26 18:59:04 -0800 -0800 -0800 -0800 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 +0100 -0800 -0800 -0800 -0800 -0800 -0800 -0800 12) 13) 14) 15) 16) 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29) 30) 31) 32) 33) 34) 35) 36) 37) 38) #define PACK_SIGN #define PACK_VERS @implementation G @synthesize @synthesize @synthesize @synthesize gitRe needR gitSo refDi

- (id) initWithGi { gitRepo = needRefs = gitSocket return sel } - (bool) uploadPa { NSLog(@"up NSString * NSArray *t refDict =

Bisecting

binary search for where a bug was introduced

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table and $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect start $ git bisect bad $ git bisect good 3acb4c2c6666ed6cb91cb0b983efe9d50cf8cfbe Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@gmail.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config

$ git bisect reset

Customizing

Autocorrect

$ git com git: 'com' is not a git-command. See 'git --help'.

Did you mean this? commit

$ git com git: 'com' is not a git-command. See 'git --help'.

Did you mean this? commit

help.autocorrect

$ git config --global help.autocorrect 1

$ git com WARNING: You called a Git program named 'com', which does not exist. Continuing under the assumption that you meant 'commit'

Colors

$ git config --global color.ui true

Custom Merge Tool

perforce visual merge tool

http://www.perforce.com/perforce/products/merge.html

$ cat /usr/local/bin/extMerge #!/bin/sh /Applications/p4merge.app/Contents/MacOS/p4merge $*

$ git config --global merge.tool extMerge $ git config --global mergetool.extMerge.cmd 'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"' $ git config --global mergetool.trustExitCode = false

~/.gitconfig
[merge] tool = extMerge [mergetool "extMerge"] cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED" trustExitCode = false

git mergetool

Git Attributes

.gitattributes

Diff Binary Files

Images

diff --git a/image.png b/image.png index 88839c4..4afcb7c 100644 Binary files a/image.png and b/image.png differ

tell Git how to diff a binary file

exiftool

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

every file that ends in .png

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

pre-process them with a strategy called ‘exif’

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

the ‘exif’ strategy is to run ‘exiftool’ on it

$ exiftool image.png ExifTool Version Number File Name Directory File Size File Modification Date/Time File Type MIME Type Image Width Image Height Bit Depth Color Type Compression Filter Interlace Profile CMM Type Profile Version Profile Class Color Space Data Profile Connection Space Profile Date Time Profile File Signature Primary Platform CMM Flags Device Manufacturer Device Model Device Attributes Rendering Intent Connection Space Illuminant Profile Creator Profile ID Red Matrix Column Green Matrix Column Blue Matrix Column Media White Point Chromatic Adaptation Red Tone Reproduction Curve Green Tone Reproduction Curve

: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :

7.74 image.png . 94 kB 2009:04:21 07:02:43-07:00 PNG image/png 1056 827 8 RGB with Alpha Deflate/Inflate Adaptive Noninterlaced appl 2.0.0 Display Device Profile RGB XYZ 2009:04:05 12:26:58 acsp Apple Computer Inc. Not Embedded, Independent

Reflective, Glossy, Positive, Color Perceptual 0.9642 1 0.82491 appl 0 0.39493 0.22505 0.02957 0.42793 0.69208 0.14424 0.14134 0.08327 0.65096 0.95047 1 1.0891 1.04788 0.02292 -0.0502 0.02957 0.99049 -0.01706 -0.00923 0.01508 0.75165 (Binary data 14 bytes, use -b option to extract) (Binary data 14 bytes, use -b option to extract)

$ echo '*.png diff=exif' >> .gitattributes $ git config diff.exif.textconv exiftool

diff --git a/image.png b/image.png index 88839c4..4afcb7c 100644 --- a/image.png +++ b/image.png @@ -1,12 +1,12 @@ ExifTool Version Number : -File Size : -File Modification Date/Time : +File Size : +File Modification Date/Time : File Type : MIME Type : -Image Width : -Image Height : +Image Width : +Image Height : Bit Depth : Color Type :

7.74 70 kB 2009:04:21 07:02:45-07:00 94 kB 2009:04:21 07:02:43-07:00 PNG image/png 1058 889 1056 827 8 RGB with Alpha

Documents

$ echo '*.doc diff=doc' >> .gitattributes $ git config diff.doc.textconv strings

$ git diff diff --git a/chapter1.doc b/chapter1.doc index c1c8a0a..b93c9e4 100644 --- a/chapter1.doc +++ b/chapter1.doc @@ -8,7 +8,8 @@ re going to cover Version Control System re going to cover how to get it and set it up for the f t already have it on your system. In Chapter Two we will go over basic Git usage - how to -s going on, modify stuff and contribute changes. If the +s going on, modify stuff and contribute changes. If the +Let's see if this works. Chapter Three is about the branching model in Git, ofte

$ git diff diff --git a/chapter1.doc b/chapter1.doc index c1c8a0a..b93c9e4 100644 --- a/chapter1.doc +++ b/chapter1.doc @@ -8,7 +8,8 @@ re going to cover Version Control System re going to cover how to get it and set it up for the f t already have it on your system. In Chapter Two we will go over basic Git usage - how to -s going on, modify stuff and contribute changes. If the +s going on, modify stuff and contribute changes. If the +Let's see if this works. Chapter Three is about the branching model in Git, ofte

File Filtering

Staging Area

fileA.txt

fileB.txt

fileC.rb

Staging Area

*.txt Filter
fileA.txt

smudge

fileB.txt

clean

fileC.rb

Staging Area

*.txt Filter
fileA.txt

smudge

fileB.txt

clean

fileC.rb

git checkout

Staging Area *.txt Filter
fileA.txt smudge

Working Directory

fileA.txt'

fileB.txt

clean

fileB.txt'

fileC.rb

fileC.rb

git checkout

Staging Area *.txt Filter
fileA.txt smudge

Working Directory

fileA.txt'

fileB.txt

clean

fileB.txt'

fileC.rb

fileC.rb

Staging Area *.txt Filter
fileA.txt smudge

Working Directory

fileA.txt'

fileB.txt

clean

fileB.txt'

fileC.rb

fileC.rb

git commit

Staging Area

Working Directory

*.txt Filter
fileA.txt smudge fileA.txt'

fileB.txt

clean

fileB.txt'

fileC.rb

fileC.rb

git commit

expanding a $Date$

/usr/bin/expand_date
#! /usr/bin/env ruby data = STDIN.read date = `git log --pretty=format:"%ad" -1` puts data.gsub('$Date$', '$Date: ' + date + '$')

git config filter.dater.smudge expand_date git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'

git config filter.dater.smudge expand_date git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'

replace $Date(whatever)$ with $Date$

git config filter.dater.smudge expand_date git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'

replace $Date(whatever)$ with $Date$

test it

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ $ # git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb cat date_test.rb $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ $ # git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb cat date_test.rb $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ $ # git add date_test.rb .gitattributes use commit -m "Testing date expansion in Git" git the ‘dater’ filter for any files matching ‘date*.rb’ rm date_test.rb git checkout date_test.rb cat date_test.rb $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ $ # git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb cat date_test.rb $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ $ # git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb cat date_test.rb $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb

$ cat date_test.rb # $Date: Tue Apr 21 07:26:52 2009 -0700$

$ echo '# $Date$' > date_test.rb $ echo 'date*.rb filter=dater' >> .gitattributes $ $ $ $ git add date_test.rb .gitattributes git commit -m "Testing date expansion in Git" rm date_test.rb git checkout date_test.rb

$ cat date_test.rb # $Date: Tue Apr 21 07:26:52 2009 -0700$

</tricks></tips>

one more thing...

2

git server

hg client

hg client

git client

hg-git.github.com

http://bitbucket.org/Scotty/hg-git/

http://github.com/schacon/hg-git

$ hg gpush github pushing to : github exporting git objects converting revision 78 creating and sending data github::refs/heads/master : f8cebef6 => ffbc960d

beta

• lossless conversion • all pushes to GitHub for the project have
been through Hg

• have pulled and merged changes introduced
on GitHub via Hg

• have pulled and merged changes introduced
on BitBucket and pushed back to GitHub

hg-git.github.com

fin

Resources
git-scm.com gitcasts.com learn.github.com #git / #github on IRC peepcode - git book and screencast schacon@gmail.com me, in person, tonight, someplace that serves whiskey