Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Agile Database Development

Agile Database Development

Hi, I'm David. I like to write database apps. Just as much as I like to write web apps. (Maybe more!) How? Not by relying on bolted-on, half-baked database integration tools like migrations, I'll tell you that!. Instead, I make extensive use of best-of-breed tools for source control ([Git](http://git-scm.org/)), database unit testing ([pgTAP](http://pgtap.org/)), and database change management and deployment ([Sqitch](http://sqitch.org/). If you'd like to get as much pleasure out of database development as you do application development, join me for this tutorial. We'll develop a sample application using the processes and tools I've come to depend on, and you'll find out whether they might work for you. Either way, I promise it will at least be an amusing use of your time.

[Originally presented at PGCon 2013](http://www.pgcon.org/2013/schedule/events/615.en.html).

David E. Wheeler

May 22, 2013
Tweet

More Decks by David E. Wheeler

Other Decks in Technology

Transcript

  1. Agile
    Database Development
    David E. Wheeler
    PGCon 2013
    Ottawa
    Text: Attribution-Noncommercial-Share Alike 3.0 United States:
    http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/
    Images licensed independently and © Their respective owners.
    iovation
    1
    Wednesday, May 22, 13

    View Slide

  2. Agile
    Database Development
    David E. Wheeler
    PGCon 2013
    Ottawa
    Text: Attribution-Noncommercial-Share Alike 3.0 United States:
    http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/
    Images licensed independently and © Their respective owners.

    iovation
    1
    Wednesday, May 22, 13

    View Slide

  3. David E. Wheeler
    PGCon 2013
    Ottawa
    Text: Attribution-Noncommercial-Share Alike 3.0 United States:
    http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/
    Images licensed independently and © Their respective owners.
    1
    Wednesday, May 22, 13

    View Slide

  4. David E. Wheeler
    PGCon 2013
    Ottawa
    License: Attribution-Noncommercial-Share Alike 3.0 United
    States: http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/
    2
    Wednesday, May 22, 13

    View Slide

  5. Build My VC-Funded App
    for Me for Free
    David E. Wheeler
    PGCon 2013
    Ottawa
    License: Attribution-Noncommercial-Share Alike 3.0 United
    States: http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/

    CEO, Data Architect
    Agile Assholes, Inc.
    2
    Wednesday, May 22, 13

    View Slide

  6. This is Genius
    3
    Wednesday, May 22, 13

    View Slide

  7. This is Genius
    I had this idea
    3
    Wednesday, May 22, 13

    View Slide

  8. This is Genius
    I had this idea
    Social networking is HAWT
    3
    Wednesday, May 22, 13

    View Slide

  9. This is Genius
    I had this idea
    Social networking is HAWT
    Has been for waaaay too long
    3
    Wednesday, May 22, 13

    View Slide

  10. This is Genius
    I had this idea
    Social networking is HAWT
    Has been for waaaay too long
    The backlash is long overdue
    3
    Wednesday, May 22, 13

    View Slide

  11. This is Genius
    I had this idea
    Social networking is HAWT
    Has been for waaaay too long
    The backlash is long overdue
    Getting ahead of the curve
    3
    Wednesday, May 22, 13

    View Slide

  12. This is Genius
    I had this idea
    Social networking is HAWT
    Has been for waaaay too long
    The backlash is long overdue
    Getting ahead of the curve
    Introducing…
    3
    Wednesday, May 22, 13

    View Slide

  13. http:/
    /flic.kr/p/8j5gG8 © 2010 Strongrrl. All rights reserved. Used with permission.
    4
    Wednesday, May 22, 13

    View Slide

  14. antisocial network
    http:/
    /flic.kr/p/8j5gG8 © 2010 Strongrrl. All rights reserved. Used with permission.
    4
    Wednesday, May 22, 13

    View Slide

  15. How it Works
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  16. How it Works
    Microblogging platform
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  17. How it Works
    Microblogging platform
    Everyone follows you
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  18. How it Works
    Microblogging platform
    Everyone follows you
    New users follow everyone
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  19. How it Works
    Microblogging platform
    Everyone follows you
    New users follow everyone
    Goal: Alienate your followers
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  20. How it Works
    Microblogging platform
    Everyone follows you
    New users follow everyone
    Goal: Alienate your followers
    Get them to unfollow you
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  21. How it Works
    Microblogging platform
    Everyone follows you
    New users follow everyone
    Goal: Alienate your followers
    Get them to unfollow you
    Leaderboard: Those with fewest followers
    antisocial network
    5
    Wednesday, May 22, 13

    View Slide

  22. Your Task
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  23. Your Task
    Create the database
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  24. Your Task
    Create the database
    Use agile development to make it right
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  25. Your Task
    Create the database
    Use agile development to make it right
    Contribute to VC-funded Corp
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  26. Your Task
    Create the database
    Use agile development to make it right
    Contribute to VC-funded Corp
    Profit!
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  27. Your Task
    Create the database
    Use agile development to make it right
    Contribute to VC-funded Corp
    Profit!
    For VC-funded Corp
    antisocial network
    6
    Wednesday, May 22, 13

    View Slide

  28. http:/
    /flic.kr/p/2honiQ © 2007 James Duncan Davidson. All rights reserved. Used with permission.
    7
    Wednesday, May 22, 13

    View Slide

  29. antisocial network
    8
    Wednesday, May 22, 13

    View Slide

  30. Agile
    WTF?
    antisocial network
    8
    Wednesday, May 22, 13

    View Slide

  31. We’ll get there
    antisocial network
    9
    Wednesday, May 22, 13

    View Slide

  32. But first…
    antisocial network
    10
    Wednesday, May 22, 13

    View Slide

  33. NDA
    antisocial network
    11
    Wednesday, May 22, 13

    View Slide

  34. Okay, now that that’s out
    of the way…
    antisocial network
    12
    Wednesday, May 22, 13

    View Slide

  35. Please organize into pairs
    antisocial network
    13
    Wednesday, May 22, 13

    View Slide

  36. Yes, that’s right
    antisocial network
    14
    Wednesday, May 22, 13

    View Slide

  37. You’re gonna do pair
    database programming
    antisocial network
    15
    Wednesday, May 22, 13

    View Slide

  38. App developers partner
    with DBAs
    antisocial network
    16
    Wednesday, May 22, 13

    View Slide

  39. I’m waiting…
    antisocial network
    17
    Wednesday, May 22, 13

    View Slide

  40. Job Requirements
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  41. Job Requirements
    PostgreSQL
    http:/
    /postgresql.org/download
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  42. Job Requirements
    PostgreSQL
    http:/
    /postgresql.org/download
    Git
    http:/
    /git-scm.com/
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  43. Job Requirements
    PostgreSQL
    http:/
    /postgresql.org/download
    Git
    http:/
    /git-scm.com/
    Sqitch
    http:/
    /sqitch.org/
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  44. Job Requirements
    PostgreSQL
    http:/
    /postgresql.org/download
    Git
    http:/
    /git-scm.com/
    Sqitch
    http:/
    /sqitch.org/
    pgTAP
    http:/
    /pgtap.org/
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  45. Job Requirements
    PostgreSQL
    http:/
    /postgresql.org/download
    Git
    http:/
    /git-scm.com/
    Sqitch
    http:/
    /sqitch.org/
    pgTAP
    http:/
    /pgtap.org/
    pg_prove
    http:/
    /metacpan.org/module/pg_prove
    antisocial network
    18
    Wednesday, May 22, 13

    View Slide

  46. We good?
    antisocial network
    19
    Wednesday, May 22, 13

    View Slide

  47. Let’s do this thang.
    antisocial network
    20
    Wednesday, May 22, 13

    View Slide

  48. >
    Who Am I?
    21
    Wednesday, May 22, 13

    View Slide

  49. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    >
    Who Am I?
    21
    Wednesday, May 22, 13

    View Slide

  50. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    >
    Who Am I?
    21
    Wednesday, May 22, 13

    View Slide

  51. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    ""git"config"**global"user.email"[email protected]
    >
    >
    Who Am I?
    21
    Wednesday, May 22, 13

    View Slide

  52. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    ""git"config"**global"user.email"[email protected]
    >
    >
    Who Am I?
    21
    Wednesday, May 22, 13

    View Slide

  53. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    ""git"config"**global"user.email"[email protected]
    >
    >
    Who Am I?
    Please use
    your own name
    and email.
    21
    Wednesday, May 22, 13

    View Slide

  54. ""git"config"**global"user.name"'David"E."Wheeler'
    >
    ""git"config"**global"user.email"[email protected]
    >
    >
    Who Am I?
    ""emacs"~/.gitconfig
    >
    21
    Wednesday, May 22, 13

    View Slide

  55. ~/.gitconfig
    ~/
    .gitconfig
    [user]
    "" name"="David"E."Wheeler
    """ email"="[email protected]
    22
    Wednesday, May 22, 13

    View Slide

  56. ~/.gitconfig
    ~/
    .gitconfig
    [user]
    "" name"="David"E."Wheeler
    """ email"="[email protected]
    Good for
    all projects
    22
    Wednesday, May 22, 13

    View Slide

  57. Create a Remote
    23
    Wednesday, May 22, 13

    View Slide

  58. Create a Remote
    Create Git project on GitHub
    23
    Wednesday, May 22, 13

    View Slide

  59. Create a Remote
    Create Git project on GitHub
    Or BitBucket
    23
    Wednesday, May 22, 13

    View Slide

  60. Create a Remote
    Create Git project on GitHub
    Or BitBucket
    Wherever you like
    23
    Wednesday, May 22, 13

    View Slide

  61. Create a Remote
    Create Git project on GitHub
    Or BitBucket
    Wherever you like
    Record remote URL
    23
    Wednesday, May 22, 13

    View Slide

  62. Create a Remote
    Create Git project on GitHub
    Or BitBucket
    Wherever you like
    Record remote URL
    23
    Wednesday, May 22, 13

    View Slide

  63. Or a Local Remote
    >
    24
    Wednesday, May 22, 13

    View Slide

  64. Or a Local Remote
    ""mkdir"flipr*remote
    >"cd"flipr*remote
    >
    >
    24
    Wednesday, May 22, 13

    View Slide

  65. Or a Local Remote
    ""mkdir"flipr*remote
    >"cd"flipr*remote
    >
    ""git"init"**bare
    Initialized"empty"Git"repository"in"flipr*remote/
    >
    >
    24
    Wednesday, May 22, 13

    View Slide

  66. Or a Local Remote
    ""mkdir"flipr*remote
    >"cd"flipr*remote
    >
    ""git"init"**bare
    Initialized"empty"Git"repository"in"flipr*remote/
    >
    >
    Remote URL is
    simply the path to
    this directory.
    24
    Wednesday, May 22, 13

    View Slide

  67. Or a Local Remote
    ""mkdir"flipr*remote
    >"cd"flipr*remote
    >
    ""git"init"**bare
    Initialized"empty"Git"repository"in"flipr*remote/
    >
    >
    ""cd"..
    >
    24
    Wednesday, May 22, 13

    View Slide

  68. Gitiup
    >
    25
    Wednesday, May 22, 13

    View Slide

  69. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    25
    Wednesday, May 22, 13

    View Slide

  70. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    25
    Wednesday, May 22, 13

    View Slide

  71. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    ""echo"Flipr"Database"Project">"README.md
    >
    25
    Wednesday, May 22, 13

    View Slide

  72. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    ""echo"Flipr"Database"Project">"README.md
    >
    ""git"add".
    >
    25
    Wednesday, May 22, 13

    View Slide

  73. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    ""echo"Flipr"Database"Project">"README.md
    >
    ""git"add".
    >
    ""git"commit"*m"'Initialize"repo,"add"README.'
    [master"(root*commit)"2c4b510]"Initialize"repo,"add"README.
    1"file"changed,"1"insertion(+)
    "create"mode"100644"README.md
    >
    25
    Wednesday, May 22, 13

    View Slide

  74. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    ""echo"Flipr"Database"Project">"README.md
    >
    ""git"add".
    >
    ""git"commit"*m"'Initialize"repo,"add"README.'
    [master"(root*commit)"2c4b510]"Initialize"repo,"add"README.
    1"file"changed,"1"insertion(+)
    "create"mode"100644"README.md
    >
    25
    Wednesday, May 22, 13

    View Slide

  75. ""mkdir"flipr*db
    >"cd"flipr*db
    >"git"init
    Initialized"empty"Git"repository"in"flipr*db/.git/
    >
    Gitiup
    >
    ""echo"Flipr"Database"Project">"README.md
    >
    ""git"add".
    >
    ""git"commit"*m"'Initialize"repo,"add"README.'
    [master"(root*commit)"2c4b510]"Initialize"repo,"add"README.
    1"file"changed,"1"insertion(+)
    "create"mode"100644"README.md
    >
    We have a
    Git repo.
    25
    Wednesday, May 22, 13

    View Slide

  76. >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  77. ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  78. ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    Or remote URL
    26
    Wednesday, May 22, 13

    View Slide

  79. ""git"push"*u"origin"master
    Counting"objects:"3,"done.
    Writing"objects:"100%"(3/3),"260"bytes,"done.
    Total"3"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""master"*>"master
    Branch"master"set"up"to"track"remote"branch"master"from"
    origin.
    >
    ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  80. ""git"push"*u"origin"master
    Counting"objects:"3,"done.
    Writing"objects:"100%"(3/3),"260"bytes,"done.
    Total"3"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""master"*>"master
    Branch"master"set"up"to"track"remote"branch"master"from"
    origin.
    >
    ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  81. ""git"push"*u"origin"master
    Counting"objects:"3,"done.
    Writing"objects:"100%"(3/3),"260"bytes,"done.
    Total"3"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""master"*>"master
    Branch"master"set"up"to"track"remote"branch"master"from"
    origin.
    >
    ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  82. ""git"push"*u"origin"master
    Counting"objects:"3,"done.
    Writing"objects:"100%"(3/3),"260"bytes,"done.
    Total"3"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""master"*>"master
    Branch"master"set"up"to"track"remote"branch"master"from"
    origin.
    >
    ""git"remote"add"origin"../flipr*remote
    >
    >
    Origin
    26
    Wednesday, May 22, 13

    View Slide

  83. Swimming Upstream
    >
    27
    Wednesday, May 22, 13

    View Slide

  84. ""git"remote"add"upstream"\
    ""https://github.com/theory/agile*flipr.git
    >
    Swimming Upstream
    >
    27
    Wednesday, May 22, 13

    View Slide

  85. ""git"remote"add"upstream"\
    ""https://github.com/theory/agile*flipr.git
    >
    Swimming Upstream
    >
    ""git"fetch"upstream
    From"https://github.com/theory/agile*flipr
    "*"[new"branch]""""""flips""""""*>"upstream/flips
    "*"[new"branch]""""""master"""""*>"upstream/master
    "*"[new"branch]""""""userfuncs""*>"upstream/userfuncs
    "*"[new"branch]""""""users""""""*>"upstream/users
    "*"[new"tag]"""""""""insert_user"*>"insert_user
    "*"[new"tag]"""""""""appschema"*>"appschema
    "*"[new"tag]"""""""""v1.0.0*r1""*>"v1.0.0*r1
    "*"[new"tag]"""""""""reltag"""""*>"reltag
    "*"[new"tag]"""""""""insert_user2"*>"insert_user2
    >
    27
    Wednesday, May 22, 13

    View Slide

  86. ""git"remote"add"upstream"\
    ""https://github.com/theory/agile*flipr.git
    >
    Swimming Upstream
    >
    ""git"fetch"upstream
    From"https://github.com/theory/agile*flipr
    "*"[new"branch]""""""flips""""""*>"upstream/flips
    "*"[new"branch]""""""master"""""*>"upstream/master
    "*"[new"branch]""""""userfuncs""*>"upstream/userfuncs
    "*"[new"branch]""""""users""""""*>"upstream/users
    "*"[new"tag]"""""""""insert_user"*>"insert_user
    "*"[new"tag]"""""""""appschema"*>"appschema
    "*"[new"tag]"""""""""v1.0.0*r1""*>"v1.0.0*r1
    "*"[new"tag]"""""""""reltag"""""*>"reltag
    "*"[new"tag]"""""""""insert_user2"*>"insert_user2
    >
    For
    resetting
    later
    27
    Wednesday, May 22, 13

    View Slide

  87. Git?
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  88. Git?
    Manage tree of files over time
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  89. Git?
    Manage tree of files over time
    Distributed development
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  90. Git?
    Manage tree of files over time
    Distributed development
    Commit changes locally
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  91. Git?
    Manage tree of files over time
    Distributed development
    Commit changes locally
    Merge to remote (origin, upstream)
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  92. Git?
    Manage tree of files over time
    Distributed development
    Commit changes locally
    Merge to remote (origin, upstream)
    Speedy, responsive
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  93. Git?
    Manage tree of files over time
    Distributed development
    Commit changes locally
    Merge to remote (origin, upstream)
    Speedy, responsive
    Flexible, robust
    antisocial network
    28
    Wednesday, May 22, 13

    View Slide

  94. Why Git?
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  95. Why Git?
    Anyone can clone
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  96. Why Git?
    Anyone can clone
    Complete repository copy
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  97. Why Git?
    Anyone can clone
    Complete repository copy
    Cheap branching
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  98. Why Git?
    Anyone can clone
    Complete repository copy
    Cheap branching
    Make and test local changes
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  99. Why Git?
    Anyone can clone
    Complete repository copy
    Cheap branching
    Make and test local changes
    Submit patches, pull requests
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  100. Why Git?
    Anyone can clone
    Complete repository copy
    Cheap branching
    Make and test local changes
    Submit patches, pull requests
    Pull from upstream
    antisocial network
    29
    Wednesday, May 22, 13

    View Slide

  101. PiSHA1
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  102. PiSHA1
    SHA1 ID for every object
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  103. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  104. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  105. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    tree ID
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  106. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    tree ID
    parent ID
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  107. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    tree ID
    parent ID
    author
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  108. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    tree ID
    parent ID
    author
    committer
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  109. PiSHA1
    SHA1 ID for every object
    commit, tag, tree, blob
    Hashed commit text includes:
    tree ID
    parent ID
    author
    committer
    message
    antisocial network
    30
    Wednesday, May 22, 13

    View Slide

  110. >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  111. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  112. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  113. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  114. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  115. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  116. >
    ""git"cat*file"commit"HEAD
    tree"8b0955fd015782a26953e20d41db5fadbb347c14
    parent"0f38581c4d19313d910c2080b3470cae07f3694e
    author"David"Wheeler""1367971872"*0700
    committer"David"Wheeler""1367971872"*0700
    Get"through""Ship"it!".
    >
    Making a hash of it
    31
    Wednesday, May 22, 13

    View Slide

  117. SHAzam!
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  118. SHAzam!
    Each commit (except first) includes parent
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  119. SHAzam!
    Each commit (except first) includes parent
    Can trace from any commit to the beginning
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  120. SHAzam!
    Each commit (except first) includes parent
    Can trace from any commit to the beginning
    Tampering (corruption) detectable
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  121. SHAzam!
    Each commit (except first) includes parent
    Can trace from any commit to the beginning
    Tampering (corruption) detectable
    Because the hash will be wrong
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  122. SHAzam!
    Each commit (except first) includes parent
    Can trace from any commit to the beginning
    Tampering (corruption) detectable
    Because the hash will be wrong
    Linus Torvalds’s “greatest invention”
    http:/
    /perl.plover.com/yak/git/
    antisocial network
    32
    Wednesday, May 22, 13

    View Slide

  123. antisocial network
    Your Turn
    33
    Wednesday, May 22, 13

    View Slide

  124. antisocial network
    Your Turn
    Configure Git
    33
    Wednesday, May 22, 13

    View Slide

  125. antisocial network
    Your Turn
    Configure Git
    Initialize repository
    33
    Wednesday, May 22, 13

    View Slide

  126. antisocial network
    Your Turn
    Configure Git
    Initialize repository
    Add origin remote
    33
    Wednesday, May 22, 13

    View Slide

  127. antisocial network
    Your Turn
    Configure Git
    Initialize repository
    Add origin remote
    Add upstream remote
    33
    Wednesday, May 22, 13

    View Slide

  128. antisocial network
    Your Turn
    Configure Git
    Initialize repository
    Add origin remote
    Add upstream remote
    https:/
    /github.com/
    theory/agile-flipr.git
    33
    Wednesday, May 22, 13

    View Slide

  129. Who am I again?
    >
    34
    Wednesday, May 22, 13

    View Slide

  130. Who am I again?
    ""sqitch"config"**user"user.name"'David"E."Wheeler'
    >
    >
    34
    Wednesday, May 22, 13

    View Slide

  131. Who am I again?
    ""sqitch"config"**user"user.name"'David"E."Wheeler'
    >
    >
    34
    Wednesday, May 22, 13

    View Slide

  132. Who am I again?
    ""sqitch"config"**user"user.email"[email protected]
    >
    ""sqitch"config"**user"user.name"'David"E."Wheeler'
    >
    >
    34
    Wednesday, May 22, 13

    View Slide

  133. Who am I again?
    ""sqitch"config"**user"user.email"[email protected]
    >
    ""sqitch"config"**user"core.pg.client"/opt/local/pgsql/bin/psql
    >
    ""sqitch"config"**user"user.name"'David"E."Wheeler'
    >
    >
    34
    Wednesday, May 22, 13

    View Slide

  134. Who am I again?
    ""sqitch"config"**user"user.email"[email protected]
    >
    ""sqitch"config"**user"core.pg.client"/opt/local/pgsql/bin/psql
    >
    ""sqitch"config"**user"user.name"'David"E."Wheeler'
    >
    ""emacs"~/.sqitch/sqitch.conf
    >
    >
    34
    Wednesday, May 22, 13

    View Slide

  135. ~/.sqitch/sqitc
    ~/
    .sqitch/sqitch.conf
    [core""pg"]
    " client"="/opt/local/pgsql/bin/psql
    [user]
    "" name"="David"E."Wheeler
    """ email"="[email protected]
    35
    Wednesday, May 22, 13

    View Slide

  136. ~/.sqitch/sqitc
    ~/
    .sqitch/sqitch.conf
    [core""pg"]
    " client"="/opt/local/pgsql/bin/psql
    [user]
    "" name"="David"E."Wheeler
    """ email"="[email protected]
    Good for
    all projects
    35
    Wednesday, May 22, 13

    View Slide

  137. >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  138. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  139. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  140. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    Use remote URL
    36
    Wednesday, May 22, 13

    View Slide

  141. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  142. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  143. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  144. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  145. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    36
    Wednesday, May 22, 13

    View Slide

  146. >"sqitch"**engine"pg"init"flipr"\
    ""**uri"file://../flipr*remote
    Created"sqitch.conf
    Created"sqitch.plan
    Created"deploy/
    Created"revert/
    Created"verify/
    >
    >
    Scratch that Sqitch
    ""emacs"sqitch.conf
    >
    36
    Wednesday, May 22, 13

    View Slide

  147. sqitch.conf
    sqitch.conf
    [core]
    " engine"="pg
    " #"plan_file"="sqitch.plan
    " #"top_dir"=".
    " #"deploy_dir"="deploy
    " #"revert_dir"="revert
    " #"verify_dir"="verify
    " #"extension"="sql
    #"[core""pg"]
    " #"client"="/usr/local/pgsql/bin/psql
    " #"username"="
    " #"password"="
    " #"db_name"="
    " #"host"="
    " #"port"="
    " #"sqitch_schema"="sqitch
    37
    Wednesday, May 22, 13

    View Slide

  148. sqitch.conf
    sqitch.conf
    [core]
    " engine"="pg
    " #"plan_file"="sqitch.plan
    " #"top_dir"=".
    " #"deploy_dir"="deploy
    " #"revert_dir"="revert
    " #"verify_dir"="verify
    " #"extension"="sql
    #"[core""pg"]
    " #"client"="/usr/local/pgsql/bin/psql
    " #"username"="
    " #"password"="
    " #"db_name"="
    " #"host"="
    " #"port"="
    " #"sqitch_schema"="sqitch
    --engine pg
    37
    Wednesday, May 22, 13

    View Slide

  149. What’s the Plan Man?
    >
    38
    Wednesday, May 22, 13

    View Slide

  150. What’s the Plan Man?
    ""emacs"sqitch.plan
    >
    >
    38
    Wednesday, May 22, 13

    View Slide

  151. sqitch.plan
    sqitch.plan
    %syntax*version=1.0.0*b1
    %project=flipr
    %uri=file://../flipr*remote
    39
    Wednesday, May 22, 13

    View Slide

  152. sqitch.plan
    sqitch.plan
    %syntax*version=1.0.0*b1
    %project=flipr
    %uri=file://../flipr*remote
    Identified
    39
    Wednesday, May 22, 13

    View Slide

  153. Make It So
    >
    40
    Wednesday, May 22, 13

    View Slide

  154. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    40
    Wednesday, May 22, 13

    View Slide

  155. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    40
    Wednesday, May 22, 13

    View Slide

  156. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    40
    Wednesday, May 22, 13

    View Slide

  157. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    ""git"push
    Counting"objects:"5,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(4/4),"done.
    Writing"objects:"100%"(4/4),"564"bytes,"done.
    Total"4"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    """7d28be0..297c07d""master"*>"master
    >
    40
    Wednesday, May 22, 13

    View Slide

  158. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    ""git"push
    Counting"objects:"5,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(4/4),"done.
    Writing"objects:"100%"(4/4),"564"bytes,"done.
    Total"4"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    """7d28be0..297c07d""master"*>"master
    >
    40
    Wednesday, May 22, 13

    View Slide

  159. Make It So
    >
    ""git"add".
    >"git"commit"*m"'Initialize"Sqitch"configuration.'
    [master"297c07d]"Initialize"Sqitch"configuration.
    "2"files"changed,"20"insertions(+)
    "create"mode"100644"sqitch.conf
    "create"mode"100644"sqitch.plan
    >
    ""git"push
    Counting"objects:"5,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(4/4),"done.
    Writing"objects:"100%"(4/4),"564"bytes,"done.
    Total"4"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    """7d28be0..297c07d""master"*>"master
    >
    40
    Wednesday, May 22, 13

    View Slide

  160. Where’ve We Been?
    >
    41
    Wednesday, May 22, 13

    View Slide

  161. ""git"log
    commit"a4f765f88c1875ffe9427e73f72a6b66ce363ed4
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"15:00:33"2013"*0400
    """"Initialize"Sqitch"configuration.
    commit"2c4b51017929634a30f4a74e20268c05effdfcb3
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"14:59:16"2013"*0400
    """"Initialize"repo,"add"README.
    >
    Where’ve We Been?
    >
    41
    Wednesday, May 22, 13

    View Slide

  162. ""git"log
    commit"a4f765f88c1875ffe9427e73f72a6b66ce363ed4
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"15:00:33"2013"*0400
    """"Initialize"Sqitch"configuration.
    commit"2c4b51017929634a30f4a74e20268c05effdfcb3
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"14:59:16"2013"*0400
    """"Initialize"repo,"add"README.
    >
    Where’ve We Been?
    >
    41
    Wednesday, May 22, 13

    View Slide

  163. ""git"log
    commit"a4f765f88c1875ffe9427e73f72a6b66ce363ed4
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"15:00:33"2013"*0400
    """"Initialize"Sqitch"configuration.
    commit"2c4b51017929634a30f4a74e20268c05effdfcb3
    Author:"David"E."Wheeler"
    Date:"""Tue"May"21"14:59:16"2013"*0400
    """"Initialize"repo,"add"README.
    >
    Where’ve We Been?
    >
    41
    Wednesday, May 22, 13

    View Slide

  164. First Change
    >
    42
    Wednesday, May 22, 13

    View Slide

  165. First Change
    >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    >
    42
    Wednesday, May 22, 13

    View Slide

  166. First Change
    >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    >
    42
    Wednesday, May 22, 13

    View Slide

  167. First Change
    >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    >
    42
    Wednesday, May 22, 13

    View Slide

  168. First Change
    >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    >
    ""emacs"deploy/appschema.sql
    >
    42
    Wednesday, May 22, 13

    View Slide

  169. deploy/appschem
    deploy/appschema.sql
    **"Deploy"appschema
    BEGIN;
    COMMIT;
    **"XXX"Add"DDLs"here.
    43
    Wednesday, May 22, 13

    View Slide

  170. deploy/appschem
    deploy/appschema.sql
    **"Deploy"appschema
    BEGIN;
    COMMIT;
    CREATE"SCHEMA"flipr;
    43
    Wednesday, May 22, 13

    View Slide

  171. >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    First Change
    >
    ""emacs"deploy/appschema.sql
    >
    44
    Wednesday, May 22, 13

    View Slide

  172. >"sqitch"add"appschema"*n"'Adds"flipr"app"schema.'
    Created"deploy/appschema.sql
    Created"revert/appschema.sql
    Created"verify/appschema.sql
    Added""appschema""to"sqitch.plan
    >
    First Change
    >
    ""emacs"deploy/appschema.sql
    >
    ""emacs"revert/appschema.sql
    >
    44
    Wednesday, May 22, 13

    View Slide

  173. revert/appschem
    revert/appschema.sql
    **"Revert"appschema
    BEGIN;
    COMMIT;
    **"XXX"Add"DDLs"here.
    45
    Wednesday, May 22, 13

    View Slide

  174. revert/appschem
    revert/appschema.sql
    **"Revert"appschema
    BEGIN;
    COMMIT;
    DROP"SCHEMA"flipr;
    45
    Wednesday, May 22, 13

    View Slide

  175. Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  176. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  177. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    Might need
    -U postgres
    46
    Wednesday, May 22, 13

    View Slide

  178. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  179. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  180. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  181. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    46
    Wednesday, May 22, 13

    View Slide

  182. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    List"of"schemas
    "Name""|"Owner"
    *******+*******
    "flipr"|"david
    >
    46
    Wednesday, May 22, 13

    View Slide

  183. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    List"of"schemas
    "Name""|"Owner"
    *******+*******
    "flipr"|"david
    >
    Trust, but
    verify
    46
    Wednesday, May 22, 13

    View Slide

  184. ""createdb"flipr_test
    >"sqitch"**db*name"flipr_test"deploy
    Adding"metadata"tables"to"flipr_test
    Deploying"to"flipr_test
    ""+"appschema".."ok
    >
    Make it So!
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    List"of"schemas
    "Name""|"Owner"
    *******+*******
    "flipr"|"david
    >
    ""emacs"verify/appschema.sql
    46
    Wednesday, May 22, 13

    View Slide

  185. **"Verify"appschema
    BEGIN;
    ROLLBACK;
    verify/appschem
    verify/appschema.sql
    **"XXX"Add"verifications"here.
    47
    Wednesday, May 22, 13

    View Slide

  186. **"Verify"appschema
    BEGIN;
    ROLLBACK;
    SELECT"pg_catalog.has_schema_privilege('nada',"'usage');
    verify/appschem
    verify/appschema.sql
    47
    Wednesday, May 22, 13

    View Slide

  187. **"Verify"appschema
    BEGIN;
    ROLLBACK;
    SELECT"pg_catalog.has_schema_privilege('nada',"'usage');
    verify/appschem
    verify/appschema.sql
    Let’s try
    it, first
    47
    Wednesday, May 22, 13

    View Slide

  188. Trust, But Verify
    >
    ""emacs"verify/appschema.sql
    >
    48
    Wednesday, May 22, 13

    View Slide

  189. Trust, But Verify
    >
    ""emacs"verify/appschema.sql
    >
    ""sqitch"**db*name"flipr_test"verify
    Verifying"flipr_test
    ""*"appschema".."psql:verify/appschema.sql:5:"
    ERROR:""schema""nada""does"not"exist
    #"Verify"script""verify/appschema.sql""failed.
    not"ok
    Verify"Summary"Report
    *********************
    Changes:"1
    Errors:""1
    Verify"failed
    >
    48
    Wednesday, May 22, 13

    View Slide

  190. Trust, But Verify
    >
    ""emacs"verify/appschema.sql
    >
    ""sqitch"**db*name"flipr_test"verify
    Verifying"flipr_test
    ""*"appschema".."psql:verify/appschema.sql:5:"
    ERROR:""schema""nada""does"not"exist
    #"Verify"script""verify/appschema.sql""failed.
    not"ok
    Verify"Summary"Report
    *********************
    Changes:"1
    Errors:""1
    Verify"failed
    >
    48
    Wednesday, May 22, 13

    View Slide

  191. Trust, But Verify
    >
    ""emacs"verify/appschema.sql
    >
    ""sqitch"**db*name"flipr_test"verify
    Verifying"flipr_test
    ""*"appschema".."psql:verify/appschema.sql:5:"
    ERROR:""schema""nada""does"not"exist
    #"Verify"script""verify/appschema.sql""failed.
    not"ok
    Verify"Summary"Report
    *********************
    Changes:"1
    Errors:""1
    Verify"failed
    >
    48
    Wednesday, May 22, 13

    View Slide

  192. Trust, But Verify
    >
    ""emacs"verify/appschema.sql
    >
    ""sqitch"**db*name"flipr_test"verify
    Verifying"flipr_test
    ""*"appschema".."psql:verify/appschema.sql:5:"
    ERROR:""schema""nada""does"not"exist
    #"Verify"script""verify/appschema.sql""failed.
    not"ok
    Verify"Summary"Report
    *********************
    Changes:"1
    Errors:""1
    Verify"failed
    >
    48
    Wednesday, May 22, 13

    View Slide

  193. Trust, But Verify
    >
    49
    Wednesday, May 22, 13

    View Slide

  194. ""perl"*i"*pe"'s/nada/flipr/'"verify/appschema.sql
    >"
    Trust, But Verify
    >
    49
    Wednesday, May 22, 13

    View Slide

  195. ""sqitch"**db*name"flipr_test"verify
    Verifying"flipr_test
    ""*"appschema".."ok
    Verify"successful
    >
    ""perl"*i"*pe"'s/nada/flipr/'"verify/appschema.sql
    >"
    Trust, But Verify
    >
    Mo betta.
    49
    Wednesday, May 22, 13

    View Slide

  196. >
    How’s it Look?
    50
    Wednesday, May 22, 13

    View Slide

  197. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  198. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  199. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  200. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  201. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  202. >
    How’s it Look?
    >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:04:08"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    50
    Wednesday, May 22, 13

    View Slide

  203. Go Back
    >
    51
    Wednesday, May 22, 13

    View Slide

  204. >"sqitch"**db*name"flipr_test"revert
    ""Revert"all"changes"from"flipr_test?"[Yes]
    Go Back
    >
    51
    Wednesday, May 22, 13

    View Slide

  205. >"sqitch"**db*name"flipr_test"revert
    ""Revert"all"changes"from"flipr_test?"[Yes]
    Go Back
    >
    51
    Wednesday, May 22, 13

    View Slide

  206. >"sqitch"**db*name"flipr_test"revert
    ""Revert"all"changes"from"flipr_test?"[Yes]
    Go Back
    >
    ""*"appschema".."ok
    >
    51
    Wednesday, May 22, 13

    View Slide

  207. >"sqitch"**db*name"flipr_test"revert
    ""Revert"all"changes"from"flipr_test?"[Yes]
    Go Back
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    """"""""""""List"of"roles
    List"of"schemas
    "Name"|"Owner"
    ******+*******
    >
    ""*"appschema".."ok
    >
    51
    Wednesday, May 22, 13

    View Slide

  208. >"sqitch"**db*name"flipr_test"revert
    ""Revert"all"changes"from"flipr_test?"[Yes]
    Go Back
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    """"""""""""List"of"roles
    List"of"schemas
    "Name"|"Owner"
    ******+*******
    >
    ""*"appschema".."ok
    >
    ""sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    No"changes"deployed
    >
    51
    Wednesday, May 22, 13

    View Slide

  209. History
    >
    52
    Wednesday, May 22, 13

    View Slide

  210. History
    >
    >"sqitch"*d"flipr_test"log
    On"database"flipr_test
    Revert"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:07:07"*0400
    """"Adds"flipr"app"schema.
    Deploy"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:04:08"*0400
    """"Adds"flipr"app"schema.
    52
    Wednesday, May 22, 13

    View Slide

  211. History
    >
    >"sqitch"*d"flipr_test"log
    On"database"flipr_test
    Revert"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:07:07"*0400
    """"Adds"flipr"app"schema.
    Deploy"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:04:08"*0400
    """"Adds"flipr"app"schema.
    52
    Wednesday, May 22, 13

    View Slide

  212. History
    >
    >"sqitch"*d"flipr_test"log
    On"database"flipr_test
    Revert"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:07:07"*0400
    """"Adds"flipr"app"schema.
    Deploy"748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    Name:""""""appschema
    Committer:"David"E."Wheeler"
    Date:""""""2013*05*21"15:04:08"*0400
    """"Adds"flipr"app"schema.
    52
    Wednesday, May 22, 13

    View Slide

  213. Commit It!
    >
    53
    Wednesday, May 22, 13

    View Slide

  214. Commit It!
    >
    ""git"add".
    >"git"commit"*m"'Add"flipr"schema.'
    [master"dc23038]"Add"flipr"schema.
    "4"files"changed,"22"insertions(+)
    "create"mode"100644"deploy/appschema.sql
    "create"mode"100644"revert/appschema.sql
    "create"mode"100644"verify/appschema.sql
    >
    53
    Wednesday, May 22, 13

    View Slide

  215. Commit It!
    >
    ""git"add".
    >"git"commit"*m"'Add"flipr"schema.'
    [master"dc23038]"Add"flipr"schema.
    "4"files"changed,"22"insertions(+)
    "create"mode"100644"deploy/appschema.sql
    "create"mode"100644"revert/appschema.sql
    "create"mode"100644"verify/appschema.sql
    >
    53
    Wednesday, May 22, 13

    View Slide

  216. Commit It!
    >
    ""git"add".
    >"git"commit"*m"'Add"flipr"schema.'
    [master"dc23038]"Add"flipr"schema.
    "4"files"changed,"22"insertions(+)
    "create"mode"100644"deploy/appschema.sql
    "create"mode"100644"revert/appschema.sql
    "create"mode"100644"verify/appschema.sql
    >
    53
    Wednesday, May 22, 13

    View Slide

  217. Commit It!
    >
    ""git"add".
    >"git"commit"*m"'Add"flipr"schema.'
    [master"dc23038]"Add"flipr"schema.
    "4"files"changed,"22"insertions(+)
    "create"mode"100644"deploy/appschema.sql
    "create"mode"100644"revert/appschema.sql
    "create"mode"100644"verify/appschema.sql
    >
    ""git"push
    Counting"objects:"11,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(6/6),"done.
    Writing"objects:"100%"(9/9),"943"bytes,"done.
    Total"9"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    """a4f765f..dc23038""master"*>"master
    53
    Wednesday, May 22, 13

    View Slide

  218. Commit It!
    >
    ""git"add".
    >"git"commit"*m"'Add"flipr"schema.'
    [master"dc23038]"Add"flipr"schema.
    "4"files"changed,"22"insertions(+)
    "create"mode"100644"deploy/appschema.sql
    "create"mode"100644"revert/appschema.sql
    "create"mode"100644"verify/appschema.sql
    >
    ""git"push
    Counting"objects:"11,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(6/6),"done.
    Writing"objects:"100%"(9/9),"943"bytes,"done.
    Total"9"(delta"0),"reused"0"(delta"0)
    To"../flipr*remote
    """a4f765f..dc23038""master"*>"master
    53
    Wednesday, May 22, 13

    View Slide

  219. Redeploy
    >
    54
    Wednesday, May 22, 13

    View Slide

  220. >"sqitch"**db*name"flipr_test"deploy"**verify
    Deploying"changes"to"flipr_test
    ""+"appschema".."ok
    >
    Redeploy
    >
    54
    Wednesday, May 22, 13

    View Slide

  221. >"sqitch"**db*name"flipr_test"deploy"**verify
    Deploying"changes"to"flipr_test
    ""+"appschema".."ok
    >
    Redeploy
    >
    Integrated!
    54
    Wednesday, May 22, 13

    View Slide

  222. >"sqitch"**db*name"flipr_test"deploy"**verify
    Deploying"changes"to"flipr_test
    ""+"appschema".."ok
    >
    Redeploy
    >
    54
    Wednesday, May 22, 13

    View Slide

  223. >"sqitch"**db*name"flipr_test"deploy"**verify
    Deploying"changes"to"flipr_test
    ""+"appschema".."ok
    >
    Redeploy
    >
    ""psql"*d"flipr_test"*c"'\dn"flipr'
    List"of"schemas
    "Name""|"Owner"
    *******+*******
    "flipr"|"david
    >
    54
    Wednesday, May 22, 13

    View Slide

  224. Status Update
    >
    55
    Wednesday, May 22, 13

    View Slide

  225. >"sqitch"*d"flipr_test"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:10:02"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    Status Update
    >
    55
    Wednesday, May 22, 13

    View Slide

  226. Save My Fingers
    >
    56
    Wednesday, May 22, 13

    View Slide

  227. Save My Fingers
    >
    ""sqitch"config"core.pg.db_name"flipr_test
    >
    56
    Wednesday, May 22, 13

    View Slide

  228. Save My Fingers
    >
    ""sqitch"config"core.pg.db_name"flipr_test
    >
    ""sqitch"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:10:02"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    No --db-name
    56
    Wednesday, May 22, 13

    View Slide

  229. Save My Fingers
    >
    ""sqitch"config"core.pg.db_name"flipr_test
    >
    ""sqitch"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:10:02"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Nothing"to"deploy"(up*to*date)
    >
    No --db-name
    >"sqitch"config"**bool"deploy.verify"true
    >"sqitch"config"**bool"rebase.verify"true
    > Always
    verify.
    56
    Wednesday, May 22, 13

    View Slide

  230. Commit Config
    >
    57
    Wednesday, May 22, 13

    View Slide

  231. Commit Config
    >
    ""git"add".
    >"git"commit"*m"'Add"db_name"and"verify"to"config.'
    [master"795697f]"Add"db_name"and"verify"to"config.
    "1"file"changed,"6"insertions(+)
    >
    57
    Wednesday, May 22, 13

    View Slide

  232. Commit Config
    >
    ""git"add".
    >"git"commit"*m"'Add"db_name"and"verify"to"config.'
    [master"795697f]"Add"db_name"and"verify"to"config.
    "1"file"changed,"6"insertions(+)
    >
    57
    Wednesday, May 22, 13

    View Slide

  233. Commit Config
    >
    ""git"push
    Counting"objects:"5,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(3/3),"done.
    Writing"objects:"100%"(3/3),"376"bytes,"done.
    Total"3"(delta"2),"reused"0"(delta"0)
    To"../flipr*remote
    """dc23038..795697f""master"*>"master
    >
    ""git"add".
    >"git"commit"*m"'Add"db_name"and"verify"to"config.'
    [master"795697f]"Add"db_name"and"verify"to"config.
    "1"file"changed,"6"insertions(+)
    >
    57
    Wednesday, May 22, 13

    View Slide

  234. Not Migrations?
    antisocial network
    58
    Wednesday, May 22, 13

    View Slide

  235. Not Migrations?
    Incomplete mini-language
    antisocial network
    58
    Wednesday, May 22, 13

    View Slide

  236. Not Migrations?
    Incomplete mini-language
    No logical replication integration
    antisocial network
    58
    Wednesday, May 22, 13

    View Slide

  237. Not Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts difficult to track
    antisocial network
    58
    Wednesday, May 22, 13

    View Slide

  238. Not Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts difficult to track
    No VCS awareness
    antisocial network
    58
    Wednesday, May 22, 13

    View Slide

  239. SQL Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts hard to track
    No VCS awareness
    antisocial network
    59
    Wednesday, May 22, 13

    View Slide

  240. SQL Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts hard to track
    No VCS awareness
    ———————————————
    antisocial network
    59
    Wednesday, May 22, 13

    View Slide

  241. SQL Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts hard to track
    No VCS awareness
    ———————————————
    ———————————————————
    antisocial network
    59
    Wednesday, May 22, 13

    View Slide

  242. SQL Migrations?
    Incomplete mini-language
    No logical replication integration
    Numbered scripts hard to track
    No VCS awareness
    ———————————————
    ———————————————————
    Managing procedures is a PITA
    antisocial network
    59
    Wednesday, May 22, 13

    View Slide

  243. Sq—what?
    sql anges
    ch
    antisocial network
    60
    Wednesday, May 22, 13

    View Slide

  244. Sq—what?
    sq ch
    antisocial network
    60
    Wednesday, May 22, 13

    View Slide

  245. it
    Sq—what?
    sq ch
    antisocial network
    60
    Wednesday, May 22, 13

    View Slide

  246. it
    Sq—what?
    sq ch
    There is no “u”
    antisocial network
    60
    Wednesday, May 22, 13

    View Slide

  247. Sqitch Philosophy
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  248. Sqitch Philosophy
    No opinions
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  249. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  250. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    Cross-project dependency resolution
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  251. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    Cross-project dependency resolution
    Distribution bundling
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  252. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    Cross-project dependency resolution
    Distribution bundling
    Integrated verification testing
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  253. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    Cross-project dependency resolution
    Distribution bundling
    Integrated verification testing
    No numbering
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  254. Sqitch Philosophy
    No opinions
    Native scripting (psql, sqlite3, SQL*Plus)
    Cross-project dependency resolution
    Distribution bundling
    Integrated verification testing
    No numbering
    Reliable sequential deployment ordering
    antisocial network
    61
    Wednesday, May 22, 13

    View Slide

  255. SHAzbat
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  256. SHAzbat
    SHA1 ID for every object
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  257. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  258. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  259. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    Hashed change text includes:
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  260. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    Hashed change text includes:
    Project
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  261. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    Hashed change text includes:
    Project
    Name
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  262. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    Hashed change text includes:
    Project
    Name
    Parent ID
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  263. SHAzbat
    SHA1 ID for every object
    Stolen from Git
    change, tag, deploy, revert, verify
    Hashed change text includes:
    Project
    Name
    Parent ID
    Planner…
    antisocial network
    62
    Wednesday, May 22, 13

    View Slide

  264. SHAsome
    >
    63
    Wednesday, May 22, 13

    View Slide

  265. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  266. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    Symbolic
    Sqitch tag
    63
    Wednesday, May 22, 13

    View Slide

  267. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  268. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  269. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  270. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  271. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  272. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  273. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  274. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  275. SHAsome
    >
    ""sqitch"show"change"@HEAD
    project"pgxn_manager
    uri"https://github.com/pgxn/pgxn*manager.git
    change"distview
    parent"39d7e105cb00e1798cfabb45f4b74cbc14a82513
    planner"David"E."Wheeler"
    date"2013*02*08T23:51:19Z
    requires
    ""+"roles
    ""+"pgxn_core:types
    ""+"distributions
    ""+"extensions
    Adds"the"filters"table.
    >
    63
    Wednesday, May 22, 13

    View Slide

  276. SHApay!
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  277. SHApay!
    Each change (except first) includes parent
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  278. SHApay!
    Each change (except first) includes parent
    Can trace from any change to the beginning
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  279. SHApay!
    Each change (except first) includes parent
    Can trace from any change to the beginning
    Change tampering (corruption) detectable
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  280. SHApay!
    Each change (except first) includes parent
    Can trace from any change to the beginning
    Change tampering (corruption) detectable
    Because the hash will be wrong
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  281. SHApay!
    Each change (except first) includes parent
    Can trace from any change to the beginning
    Change tampering (corruption) detectable
    Because the hash will be wrong
    Stole Linus Torvalds’s “greatest invention”
    antisocial network
    64
    Wednesday, May 22, 13

    View Slide

  282. Sqitch Features
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  283. Sqitch Features
    Reduced duplication
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  284. Sqitch Features
    Reduced duplication
    Built-in configuration
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  285. Sqitch Features
    Reduced duplication
    Built-in configuration
    Iterative development
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  286. Sqitch Features
    Reduced duplication
    Built-in configuration
    Iterative development
    Deployment planning
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  287. Sqitch Features
    Reduced duplication
    Built-in configuration
    Iterative development
    Deployment planning
    Git-style interface
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  288. Sqitch Features
    Reduced duplication
    Built-in configuration
    Iterative development
    Deployment planning
    Git-style interface
    Deployment tagging
    antisocial network
    65
    Wednesday, May 22, 13

    View Slide

  289. antisocial network
    Your Turn
    66
    Wednesday, May 22, 13

    View Slide

  290. antisocial network
    Your Turn
    Configure Sqitch
    66
    Wednesday, May 22, 13

    View Slide

  291. antisocial network
    Your Turn
    Configure Sqitch
    Initialize project
    66
    Wednesday, May 22, 13

    View Slide

  292. antisocial network
    Your Turn
    Configure Sqitch
    Initialize project
    Add appschema change
    66
    Wednesday, May 22, 13

    View Slide

  293. antisocial network
    Your Turn
    Configure Sqitch
    Initialize project
    Add appschema change
    Deploy/Revert
    66
    Wednesday, May 22, 13

    View Slide

  294. antisocial network
    Your Turn
    Configure Sqitch
    Initialize project
    Add appschema change
    Deploy/Revert
    Commit/push
    66
    Wednesday, May 22, 13

    View Slide

  295. antisocial network
    Your Turn
    Configure Sqitch
    Initialize project
    Add appschema change
    Deploy/Revert
    Commit/push
    https:/
    /github.com/
    theory/agile-flipr.git
    66
    Wednesday, May 22, 13

    View Slide

  296. Add Tests
    >
    67
    Wednesday, May 22, 13

    View Slide

  297. Add Tests
    >
    ""mkdir"test
    >
    67
    Wednesday, May 22, 13

    View Slide

  298. Add Tests
    >
    ""mkdir"test
    >
    ""emacs"test/appschema.sql
    >
    67
    Wednesday, May 22, 13

    View Slide

  299. test/appschema.
    pgTAP Basics
    68
    Wednesday, May 22, 13

    View Slide

  300. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  301. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  302. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  303. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  304. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  305. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  306. test/appschema.
    pgTAP Basics
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    **"Plan"the"tests.
    SELECT"plan(1);
    SELECT"has_schema('nada');
    **"Clean"up.
    SELECT"finish();
    ROLLBACK;
    68
    Wednesday, May 22, 13

    View Slide

  307. >
    Run the Test
    69
    Wednesday, May 22, 13

    View Slide

  308. >
    Run the Test
    ""pg_prove"*v"*d"flipr_test"test/appschema.sql
    test/appschema.sql".."
    1..1
    not"ok"1"*"Schema"nada"should"exist
    #"Failed"test"1:""Schema"nada"should"exist"
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/appschema.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    69
    Wednesday, May 22, 13

    View Slide

  309. >
    Run the Test
    ""pg_prove"*v"*d"flipr_test"test/appschema.sql
    test/appschema.sql".."
    1..1
    not"ok"1"*"Schema"nada"should"exist
    #"Failed"test"1:""Schema"nada"should"exist"
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/appschema.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    69
    Wednesday, May 22, 13

    View Slide

  310. >
    Run the Test
    ""pg_prove"*v"*d"flipr_test"test/appschema.sql
    test/appschema.sql".."
    1..1
    not"ok"1"*"Schema"nada"should"exist
    #"Failed"test"1:""Schema"nada"should"exist"
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/appschema.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    69
    Wednesday, May 22, 13

    View Slide

  311. First Pass
    >
    70
    Wednesday, May 22, 13

    View Slide

  312. ""perl"*i"*pe"'s/nada/flipr/'"test/appschema.sql
    >
    First Pass
    >
    70
    Wednesday, May 22, 13

    View Slide

  313. ""perl"*i"*pe"'s/nada/flipr/'"test/appschema.sql
    >
    First Pass
    >
    >"pg_prove"*v"*d"flipr_test"test/appschema.sql""""
    "
    test/appschema.sql".."
    1..1
    ok"1"*"Schema"flipr"should"exist
    ok
    All"tests"successful.
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"PASS
    70
    Wednesday, May 22, 13

    View Slide

  314. ""perl"*i"*pe"'s/nada/flipr/'"test/appschema.sql
    >
    First Pass
    W00t!
    >
    >"pg_prove"*v"*d"flipr_test"test/appschema.sql""""
    "
    test/appschema.sql".."
    1..1
    ok"1"*"Schema"flipr"should"exist
    ok
    All"tests"successful.
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"PASS
    70
    Wednesday, May 22, 13

    View Slide

  315. Pass it On
    >
    71
    Wednesday, May 22, 13

    View Slide

  316. ""git"add".
    >
    Pass it On
    >
    71
    Wednesday, May 22, 13

    View Slide

  317. ""git"add".
    >
    ""git"commit"*m"'Add"appschema"test.'
    [master"e46bdf9]"Add"appschema"test.
    "1"file"changed,"14"insertions(+)
    "create"mode"100644"test/appschema.sql
    >
    Pass it On
    >
    71
    Wednesday, May 22, 13

    View Slide

  318. ""git"add".
    >
    ""git"commit"*m"'Add"appschema"test.'
    [master"e46bdf9]"Add"appschema"test.
    "1"file"changed,"14"insertions(+)
    "create"mode"100644"test/appschema.sql
    >
    Pass it On
    >
    ""git"push
    Counting"objects:"5,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(3/3),"done.
    Writing"objects:"100%"(4/4),"487"bytes,"done.
    Total"4"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    """795697f..e46bdf9""master"*>"master
    >
    71
    Wednesday, May 22, 13

    View Slide

  319. OMG TAP WTF?
    The Test Anything Protocol (TAP) is a
    protocol to allow communication between
    unit tests and a test harness. It allows
    individual tests (TAP producers) to
    communicate test results to the testing
    harness in a language-agnostic way.
    —Wikipedia
    72
    Wednesday, May 22, 13

    View Slide

  320. What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  321. What does that mean in practice?
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  322. What does that mean in practice?
    Test output easy to interpret
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  323. What does that mean in practice?
    Test output easy to interpret
    By humans
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  324. What does that mean in practice?
    Test output easy to interpret
    By humans
    By computers
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  325. What does that mean in practice?
    Test output easy to interpret
    By humans
    By computers
    pg_prove (the harness)
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  326. What does that mean in practice?
    Test output easy to interpret
    By humans
    By computers
    pg_prove (the harness)
    By aliens
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  327. What does that mean in practice?
    Test output easy to interpret
    By humans
    By computers
    pg_prove (the harness)
    By aliens
    By gum!
    What is TAP?
    antisocial network
    73
    Wednesday, May 22, 13

    View Slide

  328. What’s the plan, man?
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  329. What’s the plan, man?
    Includes Test controls:
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  330. What’s the plan, man?
    Includes Test controls:
    plan() — How many tests?
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  331. What’s the plan, man?
    Includes Test controls:
    plan() — How many tests?
    no_plan() — Unknown number of tests
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  332. What’s the plan, man?
    Includes Test controls:
    plan() — How many tests?
    no_plan() — Unknown number of tests
    diag() — Diagnostic output
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  333. What’s the plan, man?
    Includes Test controls:
    plan() — How many tests?
    no_plan() — Unknown number of tests
    diag() — Diagnostic output
    finish() — Test finished, report!
    antisocial network
    74
    Wednesday, May 22, 13

    View Slide

  334. Scalarly
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  335. Scalarly
    Includes simple scalar test functions:
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  336. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  337. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    is() — Value comparison
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  338. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    is() — Value comparison
    isnt() — NOT is()
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  339. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    is() — Value comparison
    isnt() — NOT is()
    cmp_ok() — Compare with specific operator
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  340. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    is() — Value comparison
    isnt() — NOT is()
    cmp_ok() — Compare with specific operator
    matches() — Regex comparison
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  341. Scalarly
    Includes simple scalar test functions:
    ok() — Boolean
    is() — Value comparison
    isnt() — NOT is()
    cmp_ok() — Compare with specific operator
    matches() — Regex comparison
    imatches() — Case-insensitive regex comparison
    antisocial network
    75
    Wednesday, May 22, 13

    View Slide

  342. It’s All Relative
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  343. It’s All Relative
    Includes functions for testing relations:
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  344. It’s All Relative
    Includes functions for testing relations:
    results_eq() — Ordered results
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  345. It’s All Relative
    Includes functions for testing relations:
    results_eq() — Ordered results
    set_eq() — Set of values
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  346. It’s All Relative
    Includes functions for testing relations:
    results_eq() — Ordered results
    set_eq() — Set of values
    bag_eq() — Bag of values
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  347. It’s All Relative
    Includes functions for testing relations:
    results_eq() — Ordered results
    set_eq() — Set of values
    bag_eq() — Bag of values
    row_eq() — Single row
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  348. It’s All Relative
    Includes functions for testing relations:
    results_eq() — Ordered results
    set_eq() — Set of values
    bag_eq() — Bag of values
    row_eq() — Single row
    is_empty() — No results
    antisocial network
    76
    Wednesday, May 22, 13

    View Slide

  349. I’m Okay, You’re Okay
    antisocial network
    77
    Wednesday, May 22, 13

    View Slide

  350. I’m Okay, You’re Okay
    throws_ok() — Throws an exception
    antisocial network
    77
    Wednesday, May 22, 13

    View Slide

  351. I’m Okay, You’re Okay
    throws_ok() — Throws an exception
    throws_like() — Exception matches regex
    antisocial network
    77
    Wednesday, May 22, 13

    View Slide

  352. I’m Okay, You’re Okay
    throws_ok() — Throws an exception
    throws_like() — Exception matches regex
    skip() — Skip a subset of tests
    antisocial network
    77
    Wednesday, May 22, 13

    View Slide

  353. I’m Okay, You’re Okay
    throws_ok() — Throws an exception
    throws_like() — Exception matches regex
    skip() — Skip a subset of tests
    todo() — Expect subset of tests to fail
    antisocial network
    77
    Wednesday, May 22, 13

    View Slide

  354. Schematics
    antisocial network
    78
    Wednesday, May 22, 13

    View Slide

  355. Schematics
    has_table(), has_view(), has_function(), etc.
    antisocial network
    78
    Wednesday, May 22, 13

    View Slide

  356. Schematics
    has_table(), has_view(), has_function(), etc.
    columns_are(), has_pk(), fk_ok(), etc.
    antisocial network
    78
    Wednesday, May 22, 13

    View Slide

  357. Schematics
    has_table(), has_view(), has_function(), etc.
    columns_are(), has_pk(), fk_ok(), etc.
    col_type_is(), col_not_null(), col_default_is()
    antisocial network
    78
    Wednesday, May 22, 13

    View Slide

  358. Schematics
    has_table(), has_view(), has_function(), etc.
    columns_are(), has_pk(), fk_ok(), etc.
    col_type_is(), col_not_null(), col_default_is()
    So, so much more…
    antisocial network
    78
    Wednesday, May 22, 13

    View Slide

  359. Other Features and Topics
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  360. Other Features and Topics
    xUnit-Style testing
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  361. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  362. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  363. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  364. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    Negative assertions
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  365. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    Negative assertions
    Roles and privileges assertions
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  366. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    Negative assertions
    Roles and privileges assertions
    http:/
    /pgtap.org/
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  367. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    Negative assertions
    Roles and privileges assertions
    http:/
    /pgtap.org/
    http:/
    /pgxn.org/extension/pgtap/
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  368. Other Features and Topics
    xUnit-Style testing
    Test-Driven development
    Integration with Perl unit tests
    Integration with pg_regress
    Negative assertions
    Roles and privileges assertions
    http:/
    /pgtap.org/
    http:/
    /pgxn.org/extension/pgtap/
    antisocial network
    79
    Wednesday, May 22, 13

    View Slide

  369. antisocial network
    Let’s do it!
    80
    Wednesday, May 22, 13

    View Slide

  370. antisocial network
    Let’s do it!
    Create appschema test
    80
    Wednesday, May 22, 13

    View Slide

  371. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    80
    Wednesday, May 22, 13

    View Slide

  372. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    Run test with pg_prove
    80
    Wednesday, May 22, 13

    View Slide

  373. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    Run test with pg_prove
    Make it fail
    80
    Wednesday, May 22, 13

    View Slide

  374. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    Run test with pg_prove
    Make it fail
    Make it pass!
    80
    Wednesday, May 22, 13

    View Slide

  375. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    Run test with pg_prove
    Make it fail
    Make it pass!
    Commit/Push
    80
    Wednesday, May 22, 13

    View Slide

  376. antisocial network
    Let’s do it!
    Create appschema test
    Use pgTAP
    Run test with pg_prove
    Make it fail
    Make it pass!
    Commit/Push
    https:/
    /github.com/
    theory/agile-flipr.git
    80
    Wednesday, May 22, 13

    View Slide

  377. Let’s talk about…
    antisocial network
    antisocial network
    antisocial network
    81
    Wednesday, May 22, 13

    View Slide

  378. antisocial network
    antisocial network
    82
    Wednesday, May 22, 13

    View Slide

  379. TDD
    antisocial network
    antisocial network
    82
    Wednesday, May 22, 13

    View Slide

  380. 83
    Wednesday, May 22, 13

    View Slide

  381. “The act of writing a unit test is
    more an act of design than of
    verification. It is also more an
    act of documentation than of
    verification. The act of writing
    a unit test closes a remarkable
    number of feedback loops, the
    least of which is the one per–
    taining to the verification of
    function.”
    —Robert C. Martin
    83
    Wednesday, May 22, 13

    View Slide

  382. antisocial network
    84
    Wednesday, May 22, 13

    View Slide

  383. TDD is an act
    of design.
    antisocial network
    84
    Wednesday, May 22, 13

    View Slide

  384. antisocial network
    85
    Wednesday, May 22, 13

    View Slide

  385. TDD is an act of
    documentation.
    antisocial network
    85
    Wednesday, May 22, 13

    View Slide

  386. antisocial network
    86
    Wednesday, May 22, 13

    View Slide

  387. Okay.
    antisocial network
    86
    Wednesday, May 22, 13

    View Slide

  388. antisocial network
    87
    Wednesday, May 22, 13

    View Slide

  389. But…
    antisocial network
    87
    Wednesday, May 22, 13

    View Slide

  390. Database Design
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  391. Database Design
    Specify requirements
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  392. Database Design
    Specify requirements
    Implement schema design
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  393. Database Design
    Specify requirements
    Implement schema design
    Program applications
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  394. Database Design
    Specify requirements
    Implement schema design
    Program applications
    QA
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  395. Database Design
    Specify requirements
    Implement schema design
    Program applications
    QA
    Big jump!
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  396. Database Design
    Specify requirements
    Implement schema design
    Program applications
    QA
    Pricy to fix
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  397. Database Design
    Specify requirements
    Implement schema design
    Program applications
    QA
    Never mind bureaucracy of DBA department
    antisocial network
    88
    Wednesday, May 22, 13

    View Slide

  398. Why TDDD
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  399. Why TDDD
    Ensure data quality
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  400. Why TDDD
    Ensure data quality
    Data is a core asset
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  401. Why TDDD
    Ensure data quality
    Data is a core asset
    Validate business rules
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  402. Why TDDD
    Ensure data quality
    Data is a core asset
    Validate business rules
    Stored procedures
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  403. Why TDDD
    Ensure data quality
    Data is a core asset
    Validate business rules
    Stored procedures
    Triggers
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  404. Why TDDD
    Ensure data quality
    Data is a core asset
    Validate business rules
    Stored procedures
    Triggers
    Views
    antisocial network
    89
    Wednesday, May 22, 13

    View Slide

  405. Why TDDD
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  406. Why TDDD
    Identify defects early
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  407. Why TDDD
    Identify defects early
    …and often!
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  408. Why TDDD
    Identify defects early
    …and often!
    Create design iteratively
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  409. Why TDDD
    Identify defects early
    …and often!
    Create design iteratively
    Evolutionarily
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  410. Why TDDD
    Identify defects early
    …and often!
    Create design iteratively
    Evolutionarily
    Validate refactorings
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  411. Why TDDD
    Identify defects early
    …and often!
    Create design iteratively
    Evolutionarily
    Validate refactorings
    Make sure nothing breaks
    antisocial network
    90
    Wednesday, May 22, 13

    View Slide

  412. Three Questions
    for Database Professionals
    from
    Scott Ambler
    antisocial network
    91
    Wednesday, May 22, 13

    View Slide

  413. 92
    Wednesday, May 22, 13

    View Slide

  414. “If you’re implementing code
    in the DB in the form of
    stored procedures, triggers...
    shouldn’t you test that code
    to the same level that you
    test your app code?”
    92
    Wednesday, May 22, 13

    View Slide

  415. 93
    Wednesday, May 22, 13

    View Slide

  416. “Think of all the data quality
    problems you’ve run into
    over the years. Wouldn't it
    have been nice if someone
    had originally tested and
    discovered those problems
    before you did?”
    93
    Wednesday, May 22, 13

    View Slide

  417. 94
    Wednesday, May 22, 13

    View Slide

  418. “Wouldn’t it be nice to have
    a test suite to run so that
    you could determine how
    (and if) the DB actually
    works?”
    94
    Wednesday, May 22, 13

    View Slide

  419. antisocial network
    95
    Wednesday, May 22, 13

    View Slide

  420. Okay.
    antisocial network
    95
    Wednesday, May 22, 13

    View Slide

  421. antisocial network
    96
    Wednesday, May 22, 13

    View Slide

  422. How?
    antisocial network
    96
    Wednesday, May 22, 13

    View Slide

  423. TDD How
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  424. TDD How
    Ideally separate from app tests
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  425. TDD How
    Ideally separate from app tests
    May be many apps
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  426. TDD How
    Ideally separate from app tests
    May be many apps
    DB should present interface to all
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  427. TDD How
    Ideally separate from app tests
    May be many apps
    DB should present interface to all
    Apps may use different permissions
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  428. TDD How
    Ideally separate from app tests
    May be many apps
    DB should present interface to all
    Apps may use different permissions
    Ideally use DB test Framework
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  429. TDD How
    Ideally separate from app tests
    May be many apps
    DB should present interface to all
    Apps may use different permissions
    Ideally use DB test Framework
    Like…pgTAP!
    antisocial network
    97
    Wednesday, May 22, 13

    View Slide

  430. Branching Out
    >
    98
    Wednesday, May 22, 13

    View Slide

  431. ""git"checkout"*b"users"master
    Switched"to"a"new"branch"'users'
    >
    Branching Out
    >
    98
    Wednesday, May 22, 13

    View Slide

  432. ""git"checkout"*b"users"master
    Switched"to"a"new"branch"'users'
    >
    Branching Out
    > Branched off
    from others
    98
    Wednesday, May 22, 13

    View Slide

  433. ""git"checkout"*b"users"master
    Switched"to"a"new"branch"'users'
    >
    Branching Out
    >
    >"emacs"test/users.sql
    >
    98
    Wednesday, May 22, 13

    View Slide

  434. test/users.sql
    Table For One
    99
    Wednesday, May 22, 13

    View Slide

  435. SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    SELECT"finish();
    ROLLBACK;
    test/users.sql
    Table For One
    99
    Wednesday, May 22, 13

    View Slide

  436. SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    SELECT"finish();
    ROLLBACK;
    test/users.sql
    Table For One
    99
    Wednesday, May 22, 13

    View Slide

  437. SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    SELECT"finish();
    ROLLBACK;
    test/users.sql
    Table For One
    99
    Wednesday, May 22, 13

    View Slide

  438. SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    SELECT"finish();
    ROLLBACK;
    test/users.sql
    Table For One
    99
    Wednesday, May 22, 13

    View Slide

  439. Run ’Em
    >
    100
    Wednesday, May 22, 13

    View Slide

  440. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    not"ok"1"*"Table"users"should"exist
    #"Failed"test"1:""Table"users"should"exist"
    1..1
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    >
    Run ’Em
    >
    100
    Wednesday, May 22, 13

    View Slide

  441. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    not"ok"1"*"Table"users"should"exist
    #"Failed"test"1:""Table"users"should"exist"
    1..1
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    >
    Run ’Em
    >
    100
    Wednesday, May 22, 13

    View Slide

  442. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    not"ok"1"*"Table"users"should"exist
    #"Failed"test"1:""Table"users"should"exist"
    1..1
    #"Looks"like"you"failed"1"test"of"1
    Failed"1/1"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"1"Failed:"1)
    ""Failed"test:""1
    Files=1,"Tests=1,""0"wallclock"secs
    Result:"FAIL
    >
    Run ’Em
    As expected.
    >
    100
    Wednesday, May 22, 13

    View Slide

  443. Sqitch Dependencies!
    >
    101
    Wednesday, May 22, 13

    View Slide

  444. Sqitch Dependencies!
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >
    101
    Wednesday, May 22, 13

    View Slide

  445. Sqitch Dependencies!
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >
    101
    Wednesday, May 22, 13

    View Slide

  446. Sqitch Dependencies!
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >
    ""emacs"deploy/users.sql
    >
    101
    Wednesday, May 22, 13

    View Slide

  447. deploy/users.sq
    deploy/users.sql
    **"XXX"Add"DDLs"here.
    COMMIT;
    **"Deploy"users
    **"requires:"appschema
    BEGIN;
    102
    Wednesday, May 22, 13

    View Slide

  448. deploy/users.sq
    deploy/users.sql
    **"XXX"Add"DDLs"here.
    COMMIT;
    **"Deploy"users
    **"requires:"appschema
    BEGIN;
    102
    Wednesday, May 22, 13

    View Slide

  449. SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    );
    deploy/users.sq
    deploy/users.sql
    COMMIT;
    **"Deploy"users
    **"requires:"appschema
    BEGIN;
    102
    Wednesday, May 22, 13

    View Slide

  450. SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    );
    deploy/users.sq
    deploy/users.sql
    COMMIT;
    **"Deploy"users
    **"requires:"appschema
    BEGIN;
    Bare
    Minimum
    102
    Wednesday, May 22, 13

    View Slide

  451. Verily, Users
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >"emacs"deploy/users.sql
    >
    103
    Wednesday, May 22, 13

    View Slide

  452. Verily, Users
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >"emacs"deploy/users.sql
    >
    ""emacs"verify/users.sql
    103
    Wednesday, May 22, 13

    View Slide

  453. **"Verify"users
    BEGIN;
    verify/users.sq
    verify/users.sql
    **"XXX"Add"verifications"here.
    ROLLBACK;
    104
    Wednesday, May 22, 13

    View Slide

  454. **"Verify"users
    BEGIN;
    SELECT"nickname
    ""FROM"flipr.users
    "WHERE"FALSE;
    verify/users.sq
    verify/users.sql
    ROLLBACK;
    104
    Wednesday, May 22, 13

    View Slide

  455. Unusered
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    105
    Wednesday, May 22, 13

    View Slide

  456. Unusered
    >
    >"sqitch"add"users"**requires"appschema"\
    ""*n"'Creates"table"to"track"our"users.'
    Created"deploy/users.sql
    Created"revert/users.sql
    Created"verify/users.sql
    Added""users"[appschema]""to"sqitch.plan
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    >"emacs"revert/users.sql
    105
    Wednesday, May 22, 13

    View Slide

  457. revert/users.sq
    revert/users.sql
    **"Revert"users
    BEGIN;
    COMMIT;
    **"XXX"Add"DDLs"here.
    106
    Wednesday, May 22, 13

    View Slide

  458. revert/users.sq
    revert/users.sql
    **"Revert"users
    BEGIN;
    COMMIT;
    DROP"TABLE"flipr.users;
    106
    Wednesday, May 22, 13

    View Slide

  459. Make Users
    >
    107
    Wednesday, May 22, 13

    View Slide

  460. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Make Users
    >
    107
    Wednesday, May 22, 13

    View Slide

  461. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Make Users
    >
    107
    Wednesday, May 22, 13

    View Slide

  462. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Make Users
    >
    ""psql"*d"flipr_test"*c"'\d"flipr.users'
    """""Table""flipr.users"
    ""Column""|"Type"|"Modifiers"
    **********+******+***********
    "nickname"|"text"|"
    >
    107
    Wednesday, May 22, 13

    View Slide

  463. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Make Users
    >
    ""psql"*d"flipr_test"*c"'\d"flipr.users'
    """""Table""flipr.users"
    ""Column""|"Type"|"Modifiers"
    **********+******+***********
    "nickname"|"text"|"
    >
    ""sqitch"verify
    Verifying"flipr_test
    ""*"appschema".."ok
    ""*"users"......"ok
    Verify"successful
    >
    107
    Wednesday, May 22, 13

    View Slide

  464. Make Users
    >
    108
    Wednesday, May 22, 13

    View Slide

  465. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    1..1
    ok
    All"tests"successful.
    Files=1,"Tests=1,""1"wallclock"secs
    Result:"PASS
    >
    Make Users
    >
    108
    Wednesday, May 22, 13

    View Slide

  466. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    1..1
    ok
    All"tests"successful.
    Files=1,"Tests=1,""1"wallclock"secs
    Result:"PASS
    >
    Make Users
    >
    108
    Wednesday, May 22, 13

    View Slide

  467. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    1..1
    ok
    All"tests"successful.
    Files=1,"Tests=1,""1"wallclock"secs
    Result:"PASS
    >
    Make Users
    >
    Woohoo!
    108
    Wednesday, May 22, 13

    View Slide

  468. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    1..1
    ok
    All"tests"successful.
    Files=1,"Tests=1,""1"wallclock"secs
    Result:"PASS
    >
    Make Users
    >
    ""emacs"test/users.sql
    >
    108
    Wednesday, May 22, 13

    View Slide

  469. SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    test/users.sql
    Columnist
    SELECT"finish();
    ROLLBACK;
    109
    Wednesday, May 22, 13

    View Slide

  470. SELECT"has_column("'users',"'nickname'"");
    SELECT"has_column("'users',"'password'"");
    SELECT"has_column("'users',"'timestamp'");
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    BEGIN;
    SELECT"no_plan();
    SET"search_path"TO"flipr,public;
    SELECT"has_table("'users'");
    test/users.sql
    Columnist
    SELECT"finish();
    ROLLBACK;
    109
    Wednesday, May 22, 13

    View Slide

  471. Dead Again
    >
    110
    Wednesday, May 22, 13

    View Slide

  472. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    ok"2"*"Column"users.nickname"should"exist
    not"ok"3"*"Column"users.password"should"exist
    #"Failed"test"3:""Column"users.password"should"exist"
    not"ok"4"*"Column"users."timestamp""should"exist
    #"Failed"test"4:""Column"users."timestamp""should"exist"
    1..4
    #"Looks"like"you"failed"2"tests"of"4
    Failed"2/4"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"4"Failed:"2)
    ""Failed"tests:""3*4
    Files=1,"Tests=4,""0"wallclock"secs
    Result:"FAIL
    Dead Again
    >
    110
    Wednesday, May 22, 13

    View Slide

  473. ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    ok"2"*"Column"users.nickname"should"exist
    not"ok"3"*"Column"users.password"should"exist
    #"Failed"test"3:""Column"users.password"should"exist"
    not"ok"4"*"Column"users."timestamp""should"exist
    #"Failed"test"4:""Column"users."timestamp""should"exist"
    1..4
    #"Looks"like"you"failed"2"tests"of"4
    Failed"2/4"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"4"Failed:"2)
    ""Failed"tests:""3*4
    Files=1,"Tests=4,""0"wallclock"secs
    Result:"FAIL
    Dead Again
    >
    Guess we should
    add them.
    110
    Wednesday, May 22, 13

    View Slide

  474. MOAR Deploy
    >
    111
    Wednesday, May 22, 13

    View Slide

  475. >"emacs"deploy/users.sql
    >
    MOAR Deploy
    >
    111
    Wednesday, May 22, 13

    View Slide

  476. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    deploy/users.sq
    deploy/users.sql
    );
    COMMIT;
    112
    Wednesday, May 22, 13

    View Slide

  477. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    """""""""""""""""",
    """"password""TEXT,
    """"timestamp"TIMESTAMPTZ
    deploy/users.sq
    deploy/users.sql
    );
    COMMIT;
    112
    Wednesday, May 22, 13

    View Slide

  478. >"emacs"deploy/users.sql
    >
    Update Verify
    >
    113
    Wednesday, May 22, 13

    View Slide

  479. >"emacs"deploy/users.sql
    >
    Update Verify
    >
    ""emacs"verify/users.sql
    >
    113
    Wednesday, May 22, 13

    View Slide

  480. **"Verify"users
    BEGIN;
    SELECT"nickname
    ""FROM"flipr.users
    "WHERE"FALSE;
    COMMIT;
    verify/users.sq
    verify/users.sql
    114
    Wednesday, May 22, 13

    View Slide

  481. **"Verify"users
    BEGIN;
    SELECT"nickname
    ""FROM"flipr.users
    "WHERE"FALSE;
    COMMIT;
    ,"password,"timestamp
    verify/users.sq
    verify/users.sql
    114
    Wednesday, May 22, 13

    View Slide

  482. Revert Overhead
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    115
    Wednesday, May 22, 13

    View Slide

  483. Revert Overhead
    ""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    115
    Wednesday, May 22, 13

    View Slide

  484. Revert Overhead
    ""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    Yes, really.
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    115
    Wednesday, May 22, 13

    View Slide

  485. Revert Overhead
    ""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    115
    Wednesday, May 22, 13

    View Slide

  486. Revert Overhead
    ""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    Remove
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    115
    Wednesday, May 22, 13

    View Slide

  487. Revert Overhead
    ""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    >"emacs"deploy/users.sql
    >"emacs"verify/users.sql
    >
    What’s
    that?
    115
    Wednesday, May 22, 13

    View Slide

  488. Sqitch Tags
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  489. Sqitch Tags
    Start with @
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  490. Sqitch Tags
    Start with @
    To distinguish from changes
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  491. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  492. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    @HEAD Last change
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  493. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    @HEAD Last change
    @ROOT First change
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  494. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    @HEAD Last change
    @ROOT First change
    Two modifiers:
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  495. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    @HEAD Last change
    @ROOT First change
    Two modifiers:
    ^ Previous change
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  496. Sqitch Tags
    Start with @
    To distinguish from changes
    Two symbolic tags:
    @HEAD Last change
    @ROOT First change
    Two modifiers:
    ^ Previous change
    ~ Following change
    antisocial network
    116
    Wednesday, May 22, 13

    View Slide

  497. Specifying Changes
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  498. Specifying Changes
    users Change named “users”
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  499. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  500. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    users^ Change before users
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  501. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    users^ Change before users
    @ROOT~ Second change
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  502. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    users^ Change before users
    @ROOT~ Second change
    appschema~ Change after appschema
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  503. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    users^ Change before users
    @ROOT~ Second change
    appschema~ Change after appschema
    @HEAD^^ Third to last change
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  504. Specifying Changes
    users Change named “users”
    @HEAD^ Second to last change
    users^ Change before users
    @ROOT~ Second change
    appschema~ Change after appschema
    @HEAD^^ Third to last change
    users~4 4th change after users
    antisocial network
    117
    Wednesday, May 22, 13

    View Slide

  505. >""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    Whither Users
    >
    118
    Wednesday, May 22, 13

    View Slide

  506. >""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    Whither Users
    >
    >"psql"*d"flipr_test"*c"'\d"flipr.users'
    Did"not"find"any"relation"named""flipr.users".
    >
    118
    Wednesday, May 22, 13

    View Slide

  507. >""sqitch"revert"**to"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    >
    ""sqitch"status
    #"On"database"flipr_test
    #"Project:""flipr
    #"Change:"""748346dfe73cf2af32a8b7088fd75ad8d7aecda3
    #"Name:"""""appschema
    #"Deployed:"2013*05*21"15:10:02"*0400
    #"By:"""""""David"E."Wheeler"
    #"
    Undeployed"change:
    ""*"users
    Whither Users
    >
    >"psql"*d"flipr_test"*c"'\d"flipr.users'
    Did"not"find"any"relation"named""flipr.users".
    >
    118
    Wednesday, May 22, 13

    View Slide

  508. Whither Users
    >
    119
    Wednesday, May 22, 13

    View Slide

  509. >"sqitch"verify
    Verifying"flipr_test
    ""*"appschema".."ok
    Undeployed"change:
    ""*"users
    Verify"successful
    >
    Whither Users
    >
    119
    Wednesday, May 22, 13

    View Slide

  510. Back At It
    >
    120
    Wednesday, May 22, 13

    View Slide

  511. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Back At It
    >
    120
    Wednesday, May 22, 13

    View Slide

  512. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Back At It
    >
    Add
    120
    Wednesday, May 22, 13

    View Slide

  513. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Back At It
    >
    ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    ok"2"*"Column"users.nickname"should"exist
    ok"3"*"Column"users.password"should"exist
    ok"4"*"Column"users."timestamp""should"exist
    1..4
    ok
    All"tests"successful.
    Files=1,"Tests=4,""0"wallclock"secs
    Result:"PASS
    >
    120
    Wednesday, May 22, 13

    View Slide

  514. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Back At It
    >
    ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    ok"2"*"Column"users.nickname"should"exist
    ok"3"*"Column"users.password"should"exist
    ok"4"*"Column"users."timestamp""should"exist
    1..4
    ok
    All"tests"successful.
    Files=1,"Tests=4,""0"wallclock"secs
    Result:"PASS
    >
    Woot!
    120
    Wednesday, May 22, 13

    View Slide

  515. ""sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    Back At It
    >
    ""pg_prove"*d"flipr_test"*v"test/users.sql
    test/users.sql".."
    ok"1"*"Table"users"should"exist
    ok"2"*"Column"users.nickname"should"exist
    ok"3"*"Column"users.password"should"exist
    ok"4"*"Column"users."timestamp""should"exist
    1..4
    ok
    All"tests"successful.
    Files=1,"Tests=4,""0"wallclock"secs
    Result:"PASS
    >
    ""emacs"verify/users.sql
    120
    Wednesday, May 22, 13

    View Slide

  516. SET"search_path"="public,tap;
    BEGIN;
    SELECT"*"FROM"no_plan();
    SELECT"has_table(""'users'");
    SELECT"has_column(""""""""'users',"'timestamp'");
    test/users.sql
    SELECT"has_column(""""""""'users',"'nickname'");
    SELECT"has_column(""""""""'users',"'password'");
    SELECT"finish();
    ROLLBACK;
    121
    Wednesday, May 22, 13

    View Slide

  517. SET"search_path"="public,tap;
    BEGIN;
    SELECT"*"FROM"no_plan();
    SELECT"has_table(""'users'");
    SELECT"has_column(""""""""'users',"'timestamp'");
    test/users.sql
    SELECT"has_column(""""""""'users',"'nickname'");
    SELECT"has_column(""""""""'users',"'password'");
    SELECT"has_pk("""""'users'");
    SELECT"finish();
    ROLLBACK;
    121
    Wednesday, May 22, 13

    View Slide

  518. SELECT"col_type_is("""""""'users',"'nickname',"'text'");
    SELECT"col_hasnt_default("'users',"'nickname'");
    SELECT"col_is_pk("""""""""'users',"'nickname'");
    SET"search_path"="public,tap;
    BEGIN;
    SELECT"*"FROM"no_plan();
    SELECT"has_table(""'users'");
    SELECT"has_column(""""""""'users',"'timestamp'");
    test/users.sql
    SELECT"has_column(""""""""'users',"'nickname'");
    SELECT"has_column(""""""""'users',"'password'");
    SELECT"has_pk("""""'users'");
    SELECT"finish();
    ROLLBACK;
    121
    Wednesday, May 22, 13

    View Slide

  519. SELECT"col_type_is("""""""'users',"'nickname',"'text'");
    SELECT"col_hasnt_default("'users',"'nickname'");
    SELECT"col_is_pk("""""""""'users',"'nickname'");
    SET"search_path"="public,tap;
    BEGIN;
    SELECT"*"FROM"no_plan();
    SELECT"has_table(""'users'");
    SELECT"has_column(""""""""'users',"'timestamp'");
    test/users.sql
    SELECT"has_column(""""""""'users',"'nickname'");
    SELECT"has_column(""""""""'users',"'password'");
    SELECT"has_pk("""""'users'");
    SELECT"col_type_is("""""""'users',"'password',"'text'");
    SELECT"col_not_null(""""""'users',"'password'");
    SELECT"col_hasnt_default("'users',"'password'");
    SELECT"finish();
    ROLLBACK;
    121
    Wednesday, May 22, 13

    View Slide

  520. SELECT"col_type_is("""""""'users',"'nickname',"'text'");
    SELECT"col_hasnt_default("'users',"'nickname'");
    SELECT"col_is_pk("""""""""'users',"'nickname'");
    SET"search_path"="public,tap;
    BEGIN;
    SELECT"*"FROM"no_plan();
    SELECT"has_table(""'users'");
    SELECT"has_column(""""""""'users',"'timestamp'");
    test/users.sql
    SELECT"has_column(""""""""'users',"'nickname'");
    SELECT"has_column(""""""""'users',"'password'");
    SELECT"has_pk("""""'users'");
    SELECT"col_type_is('users',"'timestamp',"'timestamp"with"time"zone');
    SELECT"col_not_null(""""""'users',"'timestamp'");
    SELECT"col_has_default("""'users',"'timestamp'");
    SELECT"col_default_is(""""'users',"'timestamp',"'now()'");
    SELECT"col_type_is("""""""'users',"'password',"'text'");
    SELECT"col_not_null(""""""'users',"'password'");
    SELECT"col_hasnt_default("'users',"'password'");
    SELECT"finish();
    ROLLBACK;
    121
    Wednesday, May 22, 13

    View Slide

  521. Columny
    >
    122
    Wednesday, May 22, 13

    View Slide

  522. >"pg_prove"*d"flipr_test"test/users.sql
    test/users.sql".."1/?"
    #"Failed"test"2:""Table"users"should"have"a"primary"key"
    #"Failed"test"6:""Column"users(nickname)"should"be"a"primary"key"
    #"""""""""have:"NULL
    #"""""""""want:"{nickname}
    #"Failed"test"9:""Column"users.password"should"be"NOT"NULL"
    #"Failed"test"13:""Column"users."timestamp""should"be"NOT"NULL"
    #"Failed"test"14:""Column"users."timestamp""should"have"a"default"
    #"Failed"test"15:""Column"users."timestamp""should"default"to"'now()'"
    #"""""Column"users."timestamp""has"no"default
    #"Looks"like"you"failed"6"tests"of"15
    test/users.sql".."Failed"6/15"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"15"Failed:"6)
    ""Failed"tests:""2,"6,"9,"13*15
    Files=1,"Tests=15,""0"wallclock"secs
    Result:"FAIL
    Columny
    >
    122
    Wednesday, May 22, 13

    View Slide

  523. >"pg_prove"*d"flipr_test"test/users.sql
    test/users.sql".."1/?"
    #"Failed"test"2:""Table"users"should"have"a"primary"key"
    #"Failed"test"6:""Column"users(nickname)"should"be"a"primary"key"
    #"""""""""have:"NULL
    #"""""""""want:"{nickname}
    #"Failed"test"9:""Column"users.password"should"be"NOT"NULL"
    #"Failed"test"13:""Column"users."timestamp""should"be"NOT"NULL"
    #"Failed"test"14:""Column"users."timestamp""should"have"a"default"
    #"Failed"test"15:""Column"users."timestamp""should"default"to"'now()'"
    #"""""Column"users."timestamp""has"no"default
    #"Looks"like"you"failed"6"tests"of"15
    test/users.sql".."Failed"6/15"subtests"
    Test"Summary"Report
    *******************
    test/users.sql"(Wstat:"0"Tests:"15"Failed:"6)
    ""Failed"tests:""2,"6,"9,"13*15
    Files=1,"Tests=15,""0"wallclock"secs
    Result:"FAIL
    Columny
    >
    Let’s make
    it so.
    122
    Wednesday, May 22, 13

    View Slide

  524. User Typography
    >
    123
    Wednesday, May 22, 13

    View Slide

  525. ""emacs"deploy/users.sql
    >
    User Typography
    >
    123
    Wednesday, May 22, 13

    View Slide

  526. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    """"password""TEXT
    """"timestamp"TIMESTAMPTZ
    );
    COMMIT;
    deploy/users.sq
    deploy/users.sql
    ,
    ,
    124
    Wednesday, May 22, 13

    View Slide

  527. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    """"password""TEXT
    """"timestamp"TIMESTAMPTZ
    );
    COMMIT;
    deploy/users.sq
    deploy/users.sql
    ,
    """"""""PRIMARY"KEY,
    124
    Wednesday, May 22, 13

    View Slide

  528. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    """"password""TEXT
    """"timestamp"TIMESTAMPTZ
    );
    COMMIT;
    deploy/users.sq
    deploy/users.sql
    """"""""PRIMARY"KEY,
    """"""""NOT"NULL,
    124
    Wednesday, May 22, 13

    View Slide

  529. **"Deploy"users
    **"requires:"appschema
    BEGIN;
    SET"client_min_messages"="'warning';
    CREATE"TABLE"flipr.users"(
    """"nickname""TEXT
    """"password""TEXT
    """"timestamp"TIMESTAMPTZ
    );
    COMMIT;
    deploy/users.sq
    deploy/users.sql
    """"""""PRIMARY"KEY,
    """"""""NOT"NULL,
    "NOT"NULL"DEFAULT"NOW()
    124
    Wednesday, May 22, 13

    View Slide

  530. User Typography
    >"emacs"deploy/users.sql
    >
    125
    Wednesday, May 22, 13

    View Slide

  531. ""sqitch"rebase"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    User Typography
    >"emacs"deploy/users.sql
    >
    125
    Wednesday, May 22, 13

    View Slide

  532. ""sqitch"rebase"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    User Typography
    >"emacs"deploy/users.sql
    >
    125
    Wednesday, May 22, 13

    View Slide

  533. ""sqitch"rebase"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    User Typography
    >"emacs"deploy/users.sql
    >
    125
    Wednesday, May 22, 13

    View Slide

  534. ""sqitch"rebase"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    User Typography
    >"emacs"deploy/users.sql
    >
    ""pg_prove"*d"flipr_test"test/users.sql
    test/users.sql".."ok""""
    All"tests"successful.
    Files=1,"Tests=15,""0"wallclock"secs
    Result:"PASS
    >
    125
    Wednesday, May 22, 13

    View Slide

  535. ""sqitch"rebase"@HEAD^"*y
    Reverting"changes"to"appschema"from"flipr_test
    ""*"users".."ok
    Deploying"changes"to"flipr_test
    ""+"users".."ok
    >
    User Typography
    >"emacs"deploy/users.sql
    >
    ""pg_prove"*d"flipr_test"test/users.sql
    test/users.sql".."ok""""
    All"tests"successful.
    Files=1,"Tests=15,""0"wallclock"secs
    Result:"PASS
    > Boom.
    125
    Wednesday, May 22, 13

    View Slide

  536. Additives
    >
    126
    Wednesday, May 22, 13

    View Slide

  537. Additives
    >
    ""git"add".
    >
    126
    Wednesday, May 22, 13

    View Slide

  538. Additives
    >
    ""git"add".
    >
    ""git"commit"*am"'Add"users"table.'
    [users"610b318]"Add"users"table.
    "5"files"changed,"59"insertions(+)
    "create"mode"100644"deploy/users.sql
    "create"mode"100644"revert/users.sql
    "create"mode"100644"test/users.sql
    "create"mode"100644"verify/users.sql
    >
    126
    Wednesday, May 22, 13

    View Slide

  539. Pushers
    >
    127
    Wednesday, May 22, 13

    View Slide

  540. Pushers
    >
    ""git"push"**set*upstream"origin"users
    Counting"objects:"17,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(11/11),"1.53"KiB,"done.
    Total"11"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""users"*>"users
    Branch"users"set"up"to"track"remote"branch"users"
    from"origin.
    >
    127
    Wednesday, May 22, 13

    View Slide

  541. Pushers
    >
    ""git"push"**set*upstream"origin"users
    Counting"objects:"17,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(11/11),"1.53"KiB,"done.
    Total"11"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""users"*>"users
    Branch"users"set"up"to"track"remote"branch"users"
    from"origin.
    >
    127
    Wednesday, May 22, 13

    View Slide

  542. Pushers
    >
    ""git"push"**set*upstream"origin"users
    Counting"objects:"17,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(11/11),"1.53"KiB,"done.
    Total"11"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""users"*>"users
    Branch"users"set"up"to"track"remote"branch"users"
    from"origin.
    >
    127
    Wednesday, May 22, 13

    View Slide

  543. Wash, Rinse, Repeat
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  544. Wash, Rinse, Repeat
    Add failing simple test
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  545. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  546. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    Revise test
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  547. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    Revise test
    Revise and rebase change
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  548. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    Revise test
    Revise and rebase change
    Wash, Rinse, Repeat
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  549. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    Revise test
    Revise and rebase change
    Wash, Rinse, Repeat
    Commit/Push when done
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  550. Wash, Rinse, Repeat
    Add failing simple test
    Add and deploy change
    Revise test
    Revise and rebase change
    Wash, Rinse, Repeat
    Commit/Push when done
    Breathe in, breathe out
    antisocial network
    128
    Wednesday, May 22, 13

    View Slide

  551. Time to Work!
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  552. Time to Work!
    Prepare to hack!
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  553. Time to Work!
    Prepare to hack!
    git checkout master
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  554. Time to Work!
    Prepare to hack!
    git checkout master
    git branch -D users
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  555. Time to Work!
    Prepare to hack!
    git checkout master
    git branch -D users
    git checkout -b users
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  556. Time to Work!
    Prepare to hack!
    git checkout master
    git branch -D users
    git checkout -b users
    git reset --hard upstream/users
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  557. Time to Work!
    Prepare to hack!
    git checkout master
    git branch -D users
    git checkout -b users
    git reset --hard upstream/users
    git log
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  558. Time to Work!
    Prepare to hack!
    git checkout master
    git branch -D users
    git checkout -b users
    git reset --hard upstream/users
    git log
    Should be at “Add users table.”
    antisocial network
    129
    Wednesday, May 22, 13

    View Slide

  559. Caution: Hard Reset
    Ahead
    130
    Wednesday, May 22, 13

    View Slide

  560. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    130
    Wednesday, May 22, 13

    View Slide

  561. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    Deletes HEAD snapshot
    130
    Wednesday, May 22, 13

    View Slide

  562. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    Deletes HEAD snapshot
    Replaces it with new snapshot
    130
    Wednesday, May 22, 13

    View Slide

  563. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    Deletes HEAD snapshot
    Replaces it with new snapshot
    Almost un-reversible
    130
    Wednesday, May 22, 13

    View Slide

  564. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    Deletes HEAD snapshot
    Replaces it with new snapshot
    Almost un-reversible
    Useful for starting from known point
    130
    Wednesday, May 22, 13

    View Slide

  565. Caution: Hard Reset
    Ahead
    A rare destructive Git command
    Deletes HEAD snapshot
    Replaces it with new snapshot
    Almost un-reversible
    Useful for starting from known point
    USE WITH CAUTION!
    130
    Wednesday, May 22, 13

    View Slide

  566. antisocial network
    Flip Out
    131
    Wednesday, May 22, 13

    View Slide

  567. antisocial network
    Flip Out
    Create flips branch
    131
    Wednesday, May 22, 13

    View Slide

  568. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    131
    Wednesday, May 22, 13

    View Slide

  569. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    131
    Wednesday, May 22, 13

    View Slide

  570. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    nickname FK
    131
    Wednesday, May 22, 13

    View Slide

  571. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    nickname FK
    body TEXT
    131
    Wednesday, May 22, 13

    View Slide

  572. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    nickname FK
    body TEXT
    timestamptz
    131
    Wednesday, May 22, 13

    View Slide

  573. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    nickname FK
    body TEXT
    timestamptz
    Use TDDD
    131
    Wednesday, May 22, 13

    View Slide

  574. antisocial network
    Flip Out
    Create flips branch
    Create flips table
    flip_id SERIAL PK
    nickname FK
    body TEXT
    timestamptz
    Use TDDD
    https:/
    /github.com/
    theory/agile-flipr.git
    131
    Wednesday, May 22, 13

    View Slide

  575. Functional Testing
    >
    132
    Wednesday, May 22, 13

    View Slide

  576. Functional Testing
    ""git"checkout"*b"userfuncs"users
    Switched"to"a"new"branch"'userfuncs'
    >
    >
    Branches
    from users
    132
    Wednesday, May 22, 13

    View Slide

  577. Functional Testing
    ""git"checkout"*b"userfuncs"users
    Switched"to"a"new"branch"'userfuncs'
    >
    >
    ""sqitch"add"insert_user"*r"users"*r"appschema"\
    """"""*n"'Creates"a"function"to"insert"a"user.'
    Created"deploy/insert_user.sql
    Created"revert/insert_user.sql
    Created"verify/insert_user.sql
    Added""insert_user"[users"appschema]""to"sqitch.plan
    >
    132
    Wednesday, May 22, 13

    View Slide

  578. Functional Testing
    ""git"checkout"*b"userfuncs"users
    Switched"to"a"new"branch"'userfuncs'
    >
    >
    ""sqitch"add"insert_user"*r"users"*r"appschema"\
    """"""*n"'Creates"a"function"to"insert"a"user.'
    Created"deploy/insert_user.sql
    Created"revert/insert_user.sql
    Created"verify/insert_user.sql
    Added""insert_user"[users"appschema]""to"sqitch.plan
    >
    ""emacs"test/insert_user.sql
    >
    132
    Wednesday, May 22, 13

    View Slide

  579. test/insert_use
    test/insert_user.sql
    133
    Wednesday, May 22, 13

    View Slide

  580. test/insert_use
    test/insert_user.sql
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    SET"search_path"TO"flipr,public;
    133
    Wednesday, May 22, 13

    View Slide

  581. test/insert_use
    test/insert_user.sql
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    SET"search_path"TO"flipr,public;
    133
    Wednesday, May 22, 13

    View Slide

  582. test/insert_use
    test/insert_user.sql
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    SET"search_path"TO"flipr,public;
    **"Plan"the"tests.
    BEGIN;
    select"plan(11);
    133
    Wednesday, May 22, 13

    View Slide

  583. test/insert_use
    test/insert_user.sql
    SET"client_min_messages"TO"warning;
    CREATE"EXTENSION"IF"NOT"EXISTS"pgtap;
    RESET"client_min_messages;
    SET"search_path"TO"flipr,public;
    **"Plan"the"tests.
    BEGIN;
    select"plan(11);
    133
    Wednesday, May 22, 13

    View Slide

  584. test/insert_use
    SELECT"plan(11);
    134
    Wednesday, May 22, 13

    View Slide

  585. test/insert_use
    SELECT"plan(11);
    SELECT"has_function("'insert_user'");
    SELECT"has_function(
    """"'insert_user',"ARRAY['text',"'text']
    );
    SELECT"function_lang_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'sql'
    );
    SELECT"function_returns(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'void'
    );
    SELECT"volatility_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'volatile'
    );
    134
    Wednesday, May 22, 13

    View Slide

  586. test/insert_use
    SELECT"plan(11);
    SELECT"has_function("'insert_user'");
    SELECT"has_function(
    """"'insert_user',"ARRAY['text',"'text']
    );
    SELECT"function_lang_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'sql'
    );
    SELECT"function_returns(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'void'
    );
    SELECT"volatility_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'volatile'
    );
    134
    Wednesday, May 22, 13

    View Slide

  587. test/insert_use
    SELECT"plan(11);
    SELECT"has_function("'insert_user'");
    SELECT"has_function(
    """"'insert_user',"ARRAY['text',"'text']
    );
    SELECT"function_lang_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'sql'
    );
    SELECT"function_returns(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'void'
    );
    SELECT"volatility_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'volatile'
    );
    134
    Wednesday, May 22, 13

    View Slide

  588. test/insert_use
    SELECT"plan(11);
    SELECT"has_function("'insert_user'");
    SELECT"has_function(
    """"'insert_user',"ARRAY['text',"'text']
    );
    SELECT"function_lang_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'sql'
    );
    SELECT"function_returns(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'void'
    );
    SELECT"volatility_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'volatile'
    );
    134
    Wednesday, May 22, 13

    View Slide

  589. test/insert_use
    SELECT"plan(11);
    SELECT"has_function("'insert_user'");
    SELECT"has_function(
    """"'insert_user',"ARRAY['text',"'text']
    );
    SELECT"function_lang_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'sql'
    );
    SELECT"function_returns(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'void'
    );
    SELECT"volatility_is(
    """"'insert_user',"ARRAY['text',"'text'],
    """"'volatile'
    );
    134
    Wednesday, May 22, 13

    View Slide

  590. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    135
    Wednesday, May 22, 13

    View Slide

  591. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('theory',"'foo')"$$,
    """"'Insert"a"user'
    );
    SELECT"row_eq(
    """'SELECT"*"FROM"users',
    """ROW('theory',"md5('foo'),"NOW())::users,
    """'The"user"should"have"been"inserted'
    );
    135
    Wednesday, May 22, 13

    View Slide

  592. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('theory',"'foo')"$$,
    """"'Insert"a"user'
    );
    SELECT"row_eq(
    """'SELECT"*"FROM"users',
    """ROW('theory',"md5('foo'),"NOW())::users,
    """'The"user"should"have"been"inserted'
    );
    135
    Wednesday, May 22, 13

    View Slide

  593. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('theory',"'foo')"$$,
    """"'Insert"a"user'
    );
    SELECT"row_eq(
    """'SELECT"*"FROM"users',
    """ROW('theory',"md5('foo'),"NOW())::users,
    """'The"user"should"have"been"inserted'
    );
    135
    Wednesday, May 22, 13

    View Slide

  594. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('theory',"'foo')"$$,
    """"'Insert"a"user'
    );
    SELECT"row_eq(
    """'SELECT"*"FROM"users',
    """ROW('theory',"md5('foo'),"NOW())::users,
    """'The"user"should"have"been"inserted'
    );
    135
    Wednesday, May 22, 13

    View Slide

  595. test/insert_use
    test/insert_user.sql
    """"'volatile'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('theory',"'foo')"$$,
    """"'Insert"a"user'
    );
    SELECT"row_eq(
    """'SELECT"*"FROM"users',
    """ROW('theory',"md5('foo'),"NOW())::users,
    """'The"user"should"have"been"inserted'
    );
    135
    Wednesday, May 22, 13

    View Slide

  596. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    136
    Wednesday, May 22, 13

    View Slide

  597. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """"'Insert"another"user'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Both"users"should"be"present'
    );
    136
    Wednesday, May 22, 13

    View Slide

  598. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """"'Insert"another"user'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Both"users"should"be"present'
    );
    136
    Wednesday, May 22, 13

    View Slide

  599. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """"'Insert"another"user'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Both"users"should"be"present'
    );
    Includes
    dupes
    136
    Wednesday, May 22, 13

    View Slide

  600. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """"'Insert"another"user'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Both"users"should"be"present'
    );
    136
    Wednesday, May 22, 13

    View Slide

  601. test/insert_use
    test/insert_user.sql
    """'The"user"should"have"been"inserted'
    );
    SELECT"lives_ok(
    """"$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """"'Insert"another"user'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Both"users"should"be"present'
    );
    136
    Wednesday, May 22, 13

    View Slide

  602. test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  603. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  604. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  605. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    Appendix A
    137
    Wednesday, May 22, 13

    View Slide

  606. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  607. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  608. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    137
    Wednesday, May 22, 13

    View Slide

  609. SELECT"throws_ok(
    """"$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    """"23505,"**"duplicate"key"violation
    """"NULL,""**"localized"error"message
    """"'Should"get"an"error"for"duplicate"nickname'
    );
    SELECT"bag_eq(
    """"'SELECT"*"FROM"users',
    """"$$"VALUES
    """"""""('theory',""""md5('foo'),""NOW()),
    """"""""('strongrrl',"md5('w00t'),"NOW())
    """"$$,
    """"'Should"still"have"just"the"two"users'
    );
    test/insert_use
    """"'Both"users"should"be"present'
    );
    SELECT"finish();
    ROLLBACK;
    137
    Wednesday, May 22, 13

    View Slide

  610. Functional Testing
    ""emacs"test/insert_user.sql
    >
    >
    138
    Wednesday, May 22, 13

    View Slide

  611. Functional Testing
    ""emacs"test/insert_user.sql
    >
    >
    ""emacs"deploy/insert_user.sql
    >
    138
    Wednesday, May 22, 13

    View Slide

  612. deploy/insert_u
    deploy/insert_user.sql
    **"Deploy"insert_user
    **"requires:"users
    **"requires:"appschema
    BEGIN;
    **"XXX"Add"DDLs"here.
    COMMIT;
    139
    Wednesday, May 22, 13

    View Slide

  613. deploy/insert_u
    deploy/insert_user.sql
    **"Deploy"insert_user
    **"requires:"users
    **"requires:"appschema
    BEGIN;
    CREATE"OR"REPLACE"FUNCTION"flipr.insert_user(
    """"nickname"TEXT,
    """"password"TEXT
    )"RETURNS"VOID"LANGUAGE"SQL"SECURITY"DEFINER"AS"$$
    """"INSERT"INTO"flipr.users"VALUES($1,"md5($2));
    $$;
    COMMIT;
    139
    Wednesday, May 22, 13

    View Slide

  614. Functional Testing
    ""emacs"deploy/insert_user.sql
    >
    >
    140
    Wednesday, May 22, 13

    View Slide

  615. Functional Testing
    ""emacs"deploy/insert_user.sql
    >
    >
    ""emacs"revert/insert_user.sql
    >
    140
    Wednesday, May 22, 13

    View Slide

  616. revert/insert_u
    revert/insert_user.sql
    **"Revert"insert_user
    BEGIN;
    COMMIT;
    **"XXX"Add"DDLs"here.
    141
    Wednesday, May 22, 13

    View Slide

  617. revert/insert_u
    revert/insert_user.sql
    **"Revert"insert_user
    BEGIN;
    COMMIT;
    DROP"FUNCTION"flipr.insert_user(TEXT,"TEXT);
    141
    Wednesday, May 22, 13

    View Slide

  618. Functional Testing
    ""emacs"revert/insert_user.sql
    >
    >
    142
    Wednesday, May 22, 13

    View Slide

  619. Functional Testing
    ""emacs"revert/insert_user.sql
    >
    >
    ""emacs"verify/insert_user.sql
    >
    142
    Wednesday, May 22, 13

    View Slide

  620. verify/insert_u
    verify/insert_user.sql
    **"Verify"insert_user
    BEGIN;
    **"XXX"Add"DDLs"here.
    ROLLBACK;
    143
    Wednesday, May 22, 13

    View Slide

  621. verify/insert_u
    verify/insert_user.sql
    **"Verify"insert_user
    BEGIN;
    SELECT"has_function_privilege(
    """"'flipr.insert_user(text,"text)',
    """"'execute'
    );
    ROLLBACK;
    143
    Wednesday, May 22, 13

    View Slide

  622. verify/insert_u
    verify/insert_user.sql
    **"Verify"insert_user
    BEGIN;
    SELECT"has_function_privilege(
    """"'flipr.insert_user(text,"text)',
    """"'execute'
    );
    ROLLBACK;
    Convenient!
    143
    Wednesday, May 22, 13

    View Slide

  623. We Good?
    ""emacs"verify/insert_user.sql
    >
    >
    144
    Wednesday, May 22, 13

    View Slide

  624. We Good?
    ""emacs"verify/insert_user.sql
    >
    >
    ""pg_prove"*d"flipr_test"test/*.sql""""""""""
    test/appschema.sql"...."ok"""
    test/insert_user.sql".."ok"""""
    test/users.sql"........"ok""""
    All"tests"successful.
    Files=3,"Tests=27,""0"wallclock"secs
    Result:"PASS
    >
    144
    Wednesday, May 22, 13

    View Slide

  625. Commitment
    >
    145
    Wednesday, May 22, 13

    View Slide

  626. ""git"add".
    >"git"commit"*m"'Add"`insert_user()`.'
    [userfuncs"40eabe1]"Add"`insert_user()`.
    "6"files"changed,"101"insertions(+)
    "create"mode"100644"*n
    "create"mode"100644"deploy/insert_user.sql
    "create"mode"100644"revert/insert_user.sql
    "create"mode"100644"test/insert_user.sql
    "create"mode"100644"verify/insert_user.sql
    >
    Commitment
    >
    145
    Wednesday, May 22, 13

    View Slide

  627. Push It Real Good…
    >
    146
    Wednesday, May 22, 13

    View Slide

  628. ""git"push"origin"**set*upstream"userfuncs
    Counting"objects:"18,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(12/12),"1.96"KiB,"done.
    Total"12"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""userfuncs"*>"userfuncs
    Branch"userfuncs"set"up"to"track"remote"branch"
    userfuncs"from"origin.
    >
    Push It Real Good…
    >
    146
    Wednesday, May 22, 13

    View Slide

  629. ""git"push"origin"**set*upstream"userfuncs
    Counting"objects:"18,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(12/12),"1.96"KiB,"done.
    Total"12"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""userfuncs"*>"userfuncs
    Branch"userfuncs"set"up"to"track"remote"branch"
    userfuncs"from"origin.
    >
    Push It Real Good…
    >
    146
    Wednesday, May 22, 13

    View Slide

  630. ""git"push"origin"**set*upstream"userfuncs
    Counting"objects:"18,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(11/11),"done.
    Writing"objects:"100%"(12/12),"1.96"KiB,"done.
    Total"12"(delta"1),"reused"0"(delta"0)
    To"../flipr*remote
    "*"[new"branch]""""""userfuncs"*>"userfuncs
    Branch"userfuncs"set"up"to"track"remote"branch"
    userfuncs"from"origin.
    >
    Push It Real Good…
    >
    146
    Wednesday, May 22, 13

    View Slide

  631. Reset, Mes Amis!
    antisocial network
    147
    Wednesday, May 22, 13

    View Slide

  632. Reset, Mes Amis!
    git checkout users
    antisocial network
    147
    Wednesday, May 22, 13

    View Slide

  633. Reset, Mes Amis!
    git checkout users
    git reset --hard upstream/users
    antisocial network
    147
    Wednesday, May 22, 13

    View Slide

  634. Reset, Mes Amis!
    git checkout users
    git reset --hard upstream/users
    git checkout -b userfuncs
    antisocial network
    147
    Wednesday, May 22, 13

    View Slide

  635. Reset, Mes Amis!
    git checkout users
    git reset --hard upstream/users
    git checkout -b userfuncs
    git reset --hard insert_user
    antisocial network
    147
    Wednesday, May 22, 13

    View Slide

  636. antisocial network
    None Shall Pass
    148
    Wednesday, May 22, 13

    View Slide

  637. antisocial network
    None Shall Pass
    Create change_pass()
    148
    Wednesday, May 22, 13

    View Slide

  638. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    148
    Wednesday, May 22, 13

    View Slide

  639. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    148
    Wednesday, May 22, 13

    View Slide

  640. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    old_pass
    148
    Wednesday, May 22, 13

    View Slide

  641. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    old_pass
    new_pass
    148
    Wednesday, May 22, 13

    View Slide

  642. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    old_pass
    new_pass
    Only update if old pass
    correct
    148
    Wednesday, May 22, 13

    View Slide

  643. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    old_pass
    new_pass
    Only update if old pass
    correct
    Use TDDD
    148
    Wednesday, May 22, 13

    View Slide

  644. antisocial network
    None Shall Pass
    Create change_pass()
    Params:
    nickname
    old_pass
    new_pass
    Only update if old pass
    correct
    Use TDDD
    https:/
    /github.com/
    theory/agile-flipr.git
    148
    Wednesday, May 22, 13

    View Slide

  645. Resets
    >
    149
    Wednesday, May 22, 13

    View Slide

  646. >"git"reset"**hard"upstream/userfuncs
    HEAD"is"now"at"048017a"Add"`change_pass()`.
    >
    Resets
    >
    My solution
    149
    Wednesday, May 22, 13

    View Slide

  647. >"git"reset"**hard"upstream/userfuncs
    HEAD"is"now"at"048017a"Add"`change_pass()`.
    >
    >"git"checkout"master
    >
    Resets
    >
    149
    Wednesday, May 22, 13

    View Slide

  648. >"git"reset"**hard"upstream/userfuncs
    HEAD"is"now"at"048017a"Add"`change_pass()`.
    >
    ""git"reset"**hard"appschema
    HEAD"is"now"at"e46bdf9"Add"appschema"test.
    >
    >"git"checkout"master
    >
    Resets
    >
    149
    Wednesday, May 22, 13

    View Slide

  649. >"git"reset"**hard"upstream/userfuncs
    HEAD"is"now"at"048017a"Add"`change_pass()`.
    >
    ""git"reset"**hard"appschema
    HEAD"is"now"at"e46bdf9"Add"appschema"test.
    >
    >"git"checkout"master
    >
    Resets
    >
    Known good.
    149
    Wednesday, May 22, 13

    View Slide

  650. Mergers and Acquisitions
    >
    150
    Wednesday, May 22, 13

    View Slide

  651. ""git"merge"users""""""""""""""""""""""""""""""""""""""""""
    Updating"e46bdf9..610b318
    Fast*forward
    "deploy/users.sql"|"13"+++++++++++++
    "revert/users.sql"|""7"+++++++
    "sqitch.plan""""""|""1"+
    "test/users.sql"""|"29"+++++++++++++++++++++++++++++
    "verify/users.sql"|""9"+++++++++
    "5"files"changed,"59"insertions(+)
    "create"mode"100644"deploy/users.sql
    "create"mode"100644"revert/users.sql
    "create"mode"100644"test/users.sql
    "create"mode"100644"verify/users.sql
    >
    Mergers and Acquisitions
    >
    150
    Wednesday, May 22, 13

    View Slide

  652. ""git"merge"users""""""""""""""""""""""""""""""""""""""""""
    Updating"e46bdf9..610b318
    Fast*forward
    "deploy/users.sql"|"13"+++++++++++++
    "revert/users.sql"|""7"+++++++
    "sqitch.plan""""""|""1"+
    "test/users.sql"""|"29"+++++++++++++++++++++++++++++
    "verify/users.sql"|""9"+++++++++
    "5"files"changed,"59"insertions(+)
    "create"mode"100644"deploy/users.sql
    "create"mode"100644"revert/users.sql
    "create"mode"100644"test/users.sql
    "create"mode"100644"verify/users.sql
    >
    Mergers and Acquisitions
    >
    So far…
    150
    Wednesday, May 22, 13

    View Slide

  653. Mergers and Acquisitions
    >
    151
    Wednesday, May 22, 13

    View Slide

  654. >"git"merge"flips""""""""""""""""""""""""""""""""""""""""""
    Updating"610b318..fbf8469
    Fast*forward
    "deploy/flips.sql"|"15"+++++++++++++++
    "revert/flips.sql"|""7"+++++++
    "sqitch.plan""""""|""1"+
    "test/flips.sql"""|"38"+++++++++++++++++++++++++++++++++++++
    "verify/flips.sql"|"12"++++++++++++
    "5"files"changed,"73"insertions(+)
    "create"mode"100644"deploy/flips.sql
    "create"mode"100644"revert/flips.sql
    "create"mode"100644"test/flips.sql
    "create"mode"100644"verify/flips.sql
    >
    Mergers and Acquisitions
    >
    151
    Wednesday, May 22, 13

    View Slide

  655. >"git"merge"flips""""""""""""""""""""""""""""""""""""""""""
    Updating"610b318..fbf8469
    Fast*forward
    "deploy/flips.sql"|"15"+++++++++++++++
    "revert/flips.sql"|""7"+++++++
    "sqitch.plan""""""|""1"+
    "test/flips.sql"""|"38"+++++++++++++++++++++++++++++++++++++
    "verify/flips.sql"|"12"++++++++++++
    "5"files"changed,"73"insertions(+)
    "create"mode"100644"deploy/flips.sql
    "create"mode"100644"revert/flips.sql
    "create"mode"100644"test/flips.sql
    "create"mode"100644"verify/flips.sql
    >
    Mergers and Acquisitions
    >
    So good…
    151
    Wednesday, May 22, 13

    View Slide

  656. Mergers and Acquisitions
    >
    152
    Wednesday, May 22, 13

    View Slide

  657. >"git"merge"userfuncs
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Automatic"merge"failed;"fix"conflicts"and"then"
    commit"the"result.
    >
    Mergers and Acquisitions
    >
    152
    Wednesday, May 22, 13

    View Slide

  658. >"git"merge"userfuncs
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Automatic"merge"failed;"fix"conflicts"and"then"
    commit"the"result.
    >
    Mergers and Acquisitions
    >
    152
    Wednesday, May 22, 13

    View Slide

  659. >"git"merge"userfuncs
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Automatic"merge"failed;"fix"conflicts"and"then"
    commit"the"result.
    >
    Mergers and Acquisitions
    >
    152
    Wednesday, May 22, 13

    View Slide

  660. >"git"merge"userfuncs
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Automatic"merge"failed;"fix"conflicts"and"then"
    commit"the"result.
    >
    Mergers and Acquisitions
    >
    Wha???
    152
    Wednesday, May 22, 13

    View Slide

  661. Back in Time…
    >
    153
    Wednesday, May 22, 13

    View Slide

  662. Back in Time…
    ""git"checkout"*b"userfuncs"users
    Switched"to"a"new"branch"'userfuncs'
    >
    >
    153
    Wednesday, May 22, 13

    View Slide

  663. Back in Time…
    ""git"checkout"*b"userfuncs"users
    Switched"to"a"new"branch"'userfuncs'
    >
    >
    Ah-ha!
    153
    Wednesday, May 22, 13

    View Slide

  664. Branching Out
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  665. Branching Out
    users branched from master
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  666. Branching Out
    users branched from master
    flips branched from users
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  667. Branching Out
    users branched from master
    flips branched from users
    userfuncs branched from users
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  668. Branching Out
    users branched from master
    flips branched from users
    userfuncs branched from users
    users and flips merged to master
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  669. Branching Out
    users branched from master
    flips branched from users
    userfuncs branched from users
    users and flips merged to master
    userfuncs unaware of flips
    antisocial network
    154
    Wednesday, May 22, 13

    View Slide

  670. Backbrancher
    master
    A
    155
    Wednesday, May 22, 13

    View Slide

  671. Backbrancher
    master
    users
    A
    branch
    155
    Wednesday, May 22, 13

    View Slide

  672. Backbrancher
    master
    users
    A
    B
    Add
    users
    table
    branch
    155
    Wednesday, May 22, 13

    View Slide

  673. Backbrancher
    master
    users
    A
    B
    flips
    branch
    branch
    155
    Wednesday, May 22, 13

    View Slide

  674. Backbrancher
    master
    users
    A
    B
    flips
    C
    Add
    flips
    table
    branch
    branch
    155
    Wednesday, May 22, 13

    View Slide

  675. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    branch
    branch
    branch
    155
    Wednesday, May 22, 13

    View Slide

  676. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    Add
    insert_user
    function
    D
    branch
    branch
    branch
    155
    Wednesday, May 22, 13

    View Slide

  677. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    D
    branch
    branch
    branch E
    Add
    change_pass
    function
    155
    Wednesday, May 22, 13

    View Slide

  678. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    D
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  679. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    D
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  680. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    D
    F
    merge D
    &
    E
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  681. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    D
    No C!
    F
    merge D
    &
    E
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  682. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    D
    conflict!
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  683. Backbrancher
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    D
    conflict!
    Now
    what?
    branch
    branch
    branch E
    155
    Wednesday, May 22, 13

    View Slide

  684. Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch D E
    156
    Wednesday, May 22, 13

    View Slide

  685. Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch
    Last common
    with master: B
    156
    Wednesday, May 22, 13

    View Slide

  686. Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch
    C
    156
    Wednesday, May 22, 13

    View Slide

  687. Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch
    C D
    Rebased
    E
    156
    Wednesday, May 22, 13

    View Slide

  688. Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch
    C D
    E
    merge D & E
    E
    156
    Wednesday, May 22, 13

    View Slide

  689. \o/
    Rebase master
    master
    users
    A
    B
    flips
    C
    userfuncs
    B
    merge B
    C
    merge C
    branch
    branch
    branch
    C D
    E
    merge D & E
    E
    156
    Wednesday, May 22, 13

    View Slide

  690. Reset
    >
    157
    Wednesday, May 22, 13

    View Slide

  691. ""git"reset"**hard"HEAD
    HEAD"is"now"at"fbf8469"Add"flips"table.
    >
    Reset
    >
    157
    Wednesday, May 22, 13

    View Slide

  692. ""git"reset"**hard"HEAD
    HEAD"is"now"at"fbf8469"Add"flips"table.
    >
    Reset
    >
    Use with
    care!
    157
    Wednesday, May 22, 13

    View Slide

  693. ""git"reset"**hard"HEAD
    HEAD"is"now"at"fbf8469"Add"flips"table.
    >
    Reset
    >
    157
    Wednesday, May 22, 13

    View Slide

  694. ""git"reset"**hard"HEAD
    HEAD"is"now"at"fbf8469"Add"flips"table.
    >
    Reset
    >
    ""git"checkout"userfuncs
    Switched"to"branch"'userfuncs'
    >
    157
    Wednesday, May 22, 13

    View Slide

  695. Rebase
    >
    158
    Wednesday, May 22, 13

    View Slide

  696. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    >
    158
    Wednesday, May 22, 13

    View Slide

  697. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    >
    Back to B,
    apply C.
    158
    Wednesday, May 22, 13

    View Slide

  698. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    >
    That’s D
    158
    Wednesday, May 22, 13

    View Slide

  699. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    > Here comes D…
    158
    Wednesday, May 22, 13

    View Slide

  700. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    >
    D’oh!
    158
    Wednesday, May 22, 13

    View Slide

  701. >"git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    CONFLICT"(content):"Merge"conflict"in"sqitch.plan
    Failed"to"merge"in"the"changes.
    Patch"failed"at"0001"Add"`insert_user()`.
    The"copy"of"the"patch"that"failed"is"found"in:
    """/Users/david/Desktop/flipr*db/.git/rebase*apply/patch
    When"you"have"resolved"this"problem,"run""git"rebase"**contin
    If"you"prefer"to"skip"this"patch,"run""git"rebase"**skip""ins
    To"check"out"the"original"branch"and"stop"rebasing,"run""git"
    rebase"**abort".
    >
    Rebase
    >
    158
    Wednesday, May 22, 13

    View Slide

  702. Wha Happen?
    antisocial network
    159
    Wednesday, May 22, 13

    View Slide

  703. Wha Happen?
    Same conflict
    antisocial network
    159
    Wednesday, May 22, 13

    View Slide

  704. Wha Happen?
    Same conflict
    Both branches modified sqitch.plan
    antisocial network
    159
    Wednesday, May 22, 13

    View Slide

  705. Wha Happen?
    Same conflict
    Both branches modified sqitch.plan
    The same line!
    antisocial network
    159
    Wednesday, May 22, 13

    View Slide

  706. Wha Happen?
    >
    160
    Wednesday, May 22, 13

    View Slide

  707. >"git"diff
    diff"**cc"sqitch.plan
    index"0d5a515,96b1b7e..0000000
    ***"a/sqitch.plan
    +++"b/sqitch.plan
    @@@"*4,4"*4,4"+4,8"@@@
    ""
    ""appschema"2013*05*15T06:03:09Z"David"E."Wheeler"""users"[appschema]"2013*05*17T04:59:01Z"David"E."Wh
    ++<<<<<<""flips"[appschema"users]"2013*05*18T00:04:56Z"David
    ++=======
    +"insert_user"[users"appschema]"2013*05*20T20:53:56Z
    ++>>>>>>>"Add"`insert_user()`.
    >
    Wha Happen?
    >
    160
    Wednesday, May 22, 13

    View Slide

  708. >"git"diff
    diff"**cc"sqitch.plan
    index"0d5a515,96b1b7e..0000000
    ***"a/sqitch.plan
    +++"b/sqitch.plan
    @@@"*4,4"*4,4"+4,8"@@@
    ""
    ""appschema"2013*05*15T06:03:09Z"David"E."Wheeler"""users"[appschema]"2013*05*17T04:59:01Z"David"E."Wh
    ++<<<<<<""flips"[appschema"users]"2013*05*18T00:04:56Z"David
    ++=======
    +"insert_user"[users"appschema]"2013*05*20T20:53:56Z
    ++>>>>>>>"Add"`insert_user()`.
    >
    Wha Happen?
    >
    160
    Wednesday, May 22, 13

    View Slide

  709. >"git"diff
    diff"**cc"sqitch.plan
    index"0d5a515,96b1b7e..0000000
    ***"a/sqitch.plan
    +++"b/sqitch.plan
    @@@"*4,4"*4,4"+4,8"@@@
    ""
    ""appschema"2013*05*15T06:03:09Z"David"E."Wheeler"""users"[appschema]"2013*05*17T04:59:01Z"David"E."Wh
    ++<<<<<<""flips"[appschema"users]"2013*05*18T00:04:56Z"David
    ++=======
    +"insert_user"[users"appschema]"2013*05*20T20:53:56Z
    ++>>>>>>>"Add"`insert_user()`.
    >
    Wha Happen?
    >
    B
    160
    Wednesday, May 22, 13

    View Slide

  710. >"git"diff
    diff"**cc"sqitch.plan
    index"0d5a515,96b1b7e..0000000
    ***"a/sqitch.plan
    +++"b/sqitch.plan
    @@@"*4,4"*4,4"+4,8"@@@
    ""
    ""appschema"2013*05*15T06:03:09Z"David"E."Wheeler"""users"[appschema]"2013*05*17T04:59:01Z"David"E."Wh
    ++<<<<<<""flips"[appschema"users]"2013*05*18T00:04:56Z"David
    ++=======
    +"insert_user"[users"appschema]"2013*05*20T20:53:56Z
    ++>>>>>>>"Add"`insert_user()`.
    >
    Wha Happen?
    >
    C
    B
    160
    Wednesday, May 22, 13

    View Slide

  711. >"git"diff
    diff"**cc"sqitch.plan
    index"0d5a515,96b1b7e..0000000
    ***"a/sqitch.plan
    +++"b/sqitch.plan
    @@@"*4,4"*4,4"+4,8"@@@
    ""
    ""appschema"2013*05*15T06:03:09Z"David"E."Wheeler"""users"[appschema]"2013*05*17T04:59:01Z"David"E."Wh
    ++<<<<<<""flips"[appschema"users]"2013*05*18T00:04:56Z"David
    ++=======
    +"insert_user"[users"appschema]"2013*05*20T20:53:56Z
    ++>>>>>>>"Add"`insert_user()`.
    >
    Wha Happen?
    >
    C
    D
    B
    160
    Wednesday, May 22, 13

    View Slide

  712. Scratch that Sqitch
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  713. Scratch that Sqitch
    Screwed either way?
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  714. Scratch that Sqitch
    Screwed either way?
    Fortunately, this is Git
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  715. Scratch that Sqitch
    Screwed either way?
    Fortunately, this is Git
    Tell it to treat Sqitch plans differently
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  716. Scratch that Sqitch
    Screwed either way?
    Fortunately, this is Git
    Tell it to treat Sqitch plans differently
    Changes on single lines
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  717. Scratch that Sqitch
    Screwed either way?
    Fortunately, this is Git
    Tell it to treat Sqitch plans differently
    Changes on single lines
    Only appended to plan file
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  718. Scratch that Sqitch
    Screwed either way?
    Fortunately, this is Git
    Tell it to treat Sqitch plans differently
    Changes on single lines
    Only appended to plan file
    Use the “union” merge
    antisocial network
    161
    Wednesday, May 22, 13

    View Slide

  719. Re: Union Merge
    162
    Wednesday, May 22, 13

    View Slide

  720. Re: Union Merge
    Run 3-way file level merge for text files,
    but take lines from both versions, instead
    of leaving conflict markers. This tends to
    leave the added lines in the resulting file in
    random order and the user should verify
    the result. Do not use this if you do not
    understand the implications.
    —Git Manual
    162
    Wednesday, May 22, 13

    View Slide

  721. Hallelunion
    antisocial network
    163
    Wednesday, May 22, 13

    View Slide

  722. Hallelunion
    Just appends lines
    antisocial network
    163
    Wednesday, May 22, 13

    View Slide

  723. Hallelunion
    Just appends lines
    Exactly how changes work
    antisocial network
    163
    Wednesday, May 22, 13

    View Slide

  724. Hallelunion
    Just appends lines
    Exactly how changes work
    Let’s clean up our mess
    antisocial network
    163
    Wednesday, May 22, 13

    View Slide

  725. Hallelunion
    Just appends lines
    Exactly how changes work
    Let’s clean up our mess
    And try again
    antisocial network
    163
    Wednesday, May 22, 13

    View Slide

  726. Reemerge
    >
    164
    Wednesday, May 22, 13

    View Slide

  727. ""git"rebase"**abort
    >
    Reemerge
    >
    164
    Wednesday, May 22, 13

    View Slide

  728. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    164
    Wednesday, May 22, 13

    View Slide

  729. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    164
    Wednesday, May 22, 13

    View Slide

  730. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    Back to B,
    applies C
    164
    Wednesday, May 22, 13

    View Slide

  731. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    That’s D
    164
    Wednesday, May 22, 13

    View Slide

  732. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    Union merge
    164
    Wednesday, May 22, 13

    View Slide

  733. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    That’s E
    164
    Wednesday, May 22, 13

    View Slide

  734. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    Union merge
    164
    Wednesday, May 22, 13

    View Slide

  735. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    Success!
    164
    Wednesday, May 22, 13

    View Slide

  736. ""echo"sqitch.plan"merge=union">".gitattributes
    >
    ""git"rebase"master
    First,"rewinding"head"to"replay"your"work"on"top"of"it...
    Applying:"Add"`insert_user()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    Applying:"Add"`change_pass()`.
    Using"index"info"to"reconstruct"a"base"tree...
    M" sqitch.plan
    Falling"back"to"patching"base"and"3*way"merge...
    Auto*merging"sqitch.plan
    >
    ""git"rebase"**abort
    >
    Reemerge
    >
    ""emacs"sqitch.plan
    >
    Success!
    164
    Wednesday, May 22, 13

    View Slide

  737. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  738. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  739. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  740. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  741. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  742. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    165
    Wednesday, May 22, 13

    View Slide

  743. sqitch.plan
    What’s the Plan, Man?
    %syntax*version=1.0.0*b2
    %project=flipr
    %uri=file://../flipr*remote
    appschema"2013*05*21T19:01:04Z"David"E."Wheeler"
    "#"Adds"flipr"app"schema.
    users"[appschema]"2013*05*21T19:41:54Z"David"E."Wheeler"
    "#"Creates"table"to"track"our"
    users.
    flips"[appschema"users]"2013*05*21T20:38:21Z"David"E."
    Wheeler""#"Adds"table"for"storing"
    flips.
    insert_user"[users"appschema]"2013*05*21T20:51:05Z"David"
    E."Wheeler""#"Creates"a"function"to"
    insert"a"user.
    change_pass"[users"appschema]"2013*05*21T21:05:42Z"David"
    E."Wheeler""#"Creates"a"function"to
    Perfect
    165
    Wednesday, May 22, 13

    View Slide

  744. Work It
    >
    166
    Wednesday, May 22, 13

    View Slide

  745. >"sqitch"rebase"*y
    Reverting"all"changes"from"flipr_test
    ""*"change_pass".."ok
    ""*"insert_user".."ok
    ""*"users"........"ok
    ""*"appschema"...."ok
    Deploying"changes"to"flipr_test
    ""+"appschema"...."ok
    ""+"users"........"ok
    ""+"flips"........"ok
    ""+"insert_user".."ok
    ""+"change_pass".."ok
    >
    Work It
    >
    166
    Wednesday, May 22, 13

    View Slide

  746. >"sqitch"rebase"*y
    Reverting"all"changes"from"flipr_test
    ""*"change_pass".."ok
    ""*"insert_user".."ok
    ""*"users"........"ok
    ""*"appschema"...."ok
    Deploying"changes"to"flipr_test
    ""+"appschema"...."ok
    ""+"users"........"ok
    ""+"flips"........"ok
    ""+"insert_user".."ok
    ""+"change_pass".."ok
    >
    Work It
    >
    {
    166
    Wednesday, May 22, 13

    View Slide

  747. >"sqitch"rebase"*y
    Reverting"all"changes"from"flipr_test
    ""*"change_pass".."ok
    ""*"insert_user".."ok
    ""*"users"........"ok
    ""*"appschema"...."ok
    Deploying"changes"to"flipr_test
    ""+"appschema"...."ok
    ""+"users"........"ok
    ""+"flips"........"ok
    ""+"insert_user".."ok
    ""+"change_pass".."ok
    >
    Work It
    >
    {
    {
    166
    Wednesday, May 22, 13

    View Slide

  748. >"sqitch"rebase"*y
    Reverting"all"changes"from"flipr_test
    ""*"change_pass".."ok
    ""*"insert_user".."ok
    ""*"users"........"ok
    ""*"appschema"...."ok
    Deploying"changes"to"flipr_test
    ""+"appschema"...."ok
    ""+"users"........"ok
    ""+"flips"........"ok
    ""+"insert_user".."ok
    ""+"change_pass".."ok
    >
    Work It
    >
    {
    {
    Awesomsauce
    166
    Wednesday, May 22, 13

    View Slide

  749. Make it So
    >
    167
    Wednesday, May 22, 13

    View Slide

  750. >"git"add".
    >
    Make it So
    >
    167
    Wednesday, May 22, 13

    View Slide

  751. >"git"add".
    >
    ""git"commit"*m"'Use"union"merge"for"`sqitch.plan`.'
    [userfuncs"0e31da9]"Use"union"merge"for"`sqitch.plan`.
    "1"file"changed,"1"insertion(+)
    "create"mode"100644".gitattributes
    >
    Make it So
    >
    167
    Wednesday, May 22, 13

    View Slide

  752. >"git"add".
    >
    ""git"commit"*m"'Use"union"merge"for"`sqitch.plan`.'
    [userfuncs"0e31da9]"Use"union"merge"for"`sqitch.plan`.
    "1"file"changed,"1"insertion(+)
    "create"mode"100644".gitattributes
    >
    ""git"push"**force"origin"userfuncs
    Counting"objects:"31,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(24/24),"done.
    Writing"objects:"100%"(25/25),"3.83"KiB,"done.
    Total"25"(delta"7),"reused"0"(delta"0)
    To"../flipr*remote
    "+"e7477c...0e31da"userfuncs"*>"userfuncs"(forced"update
    >
    Make it So
    > Overwrite
    history
    167
    Wednesday, May 22, 13

    View Slide

  753. >"git"add".
    >
    ""git"commit"*m"'Use"union"merge"for"`sqitch.plan`.'
    [userfuncs"0e31da9]"Use"union"merge"for"`sqitch.plan`.
    "1"file"changed,"1"insertion(+)
    "create"mode"100644".gitattributes
    >
    ""git"push"**force"origin"userfuncs
    Counting"objects:"31,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(24/24),"done.
    Writing"objects:"100%"(25/25),"3.83"KiB,"done.
    Total"25"(delta"7),"reused"0"(delta"0)
    To"../flipr*remote
    "+"e7477c...0e31da"userfuncs"*>"userfuncs"(forced"update
    >
    Make it So
    >
    167
    Wednesday, May 22, 13

    View Slide

  754. >
    168
    Wednesday, May 22, 13

    View Slide

  755. >"git"checkout"master
    Switched"to"branch"'master'
    >
    >
    168
    Wednesday, May 22, 13

    View Slide

  756. ""git"merge"userfuncs
    Updating"fbf8469..0e31da9
    Fast*forward
    ".gitattributes"""""""""|""1"+
    "deploy/change_pass.sql"|"21"++++++++++++++++++
    "deploy/insert_user.sql"|"14"++++++++++++
    "revert/change_pass.sql"|""7"++++++
    "revert/insert_user.sql"|""7"++++++
    "sqitch.plan""""""""""""|""2"++
    "test/change_pass.sql"""|"52"++++++++++++++++++++++++++++++++++
    "test/insert_user.sql"""|"69"++++++++++++++++++++++++++++++++++
    "verify/change_pass.sql"|""7"++++++
    "verify/insert_user.sql"|"10"+++++++++
    "10"files"changed,"190"insertions(+)
    "create"mode"100644".gitattributes
    "create"mode"100644"deploy/change_pass.sql
    "create"mode"100644"deploy/insert_user.sql
    "create"mode"100644"revert/change_pass.sql
    "create"mode"100644"revert/insert_user.sql
    "create"mode"100644"test/change_pass.sql
    "create"mode"100644"test/insert_user.sql
    "create"mode"100644"verify/change_pass.sql
    "create"mode"100644"verify/insert_user.sql
    >
    >"git"checkout"master
    Switched"to"branch"'master'
    >
    >
    168
    Wednesday, May 22, 13

    View Slide

  757. ""git"merge"userfuncs
    Updating"fbf8469..0e31da9
    Fast*forward
    ".gitattributes"""""""""|""1"+
    "deploy/change_pass.sql"|"21"++++++++++++++++++
    "deploy/insert_user.sql"|"14"++++++++++++
    "revert/change_pass.sql"|""7"++++++
    "revert/insert_user.sql"|""7"++++++
    "sqitch.plan""""""""""""|""2"++
    "test/change_pass.sql"""|"52"++++++++++++++++++++++++++++++++++
    "test/insert_user.sql"""|"69"++++++++++++++++++++++++++++++++++
    "verify/change_pass.sql"|""7"++++++
    "verify/insert_user.sql"|"10"+++++++++
    "10"files"changed,"190"insertions(+)
    "create"mode"100644".gitattributes
    "create"mode"100644"deploy/change_pass.sql
    "create"mode"100644"deploy/insert_user.sql
    "create"mode"100644"revert/change_pass.sql
    "create"mode"100644"revert/insert_user.sql
    "create"mode"100644"test/change_pass.sql
    "create"mode"100644"test/insert_user.sql
    "create"mode"100644"verify/change_pass.sql
    "create"mode"100644"verify/insert_user.sql
    >
    >"git"checkout"master
    Switched"to"branch"'master'
    >
    >
    \O/
    168
    Wednesday, May 22, 13

    View Slide

  758. Pusher
    >
    169
    Wednesday, May 22, 13

    View Slide

  759. ""git"push
    Counting"objects:"20,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(13/13),"done.
    Writing"objects:"100%"(14/14),"2.31"KiB,"done.
    Total"14"(delta"2),"reused"0"(delta"0)
    To"../flipr*remote
    """fbf8469..0e31da9""master"*>"master
    >
    Pusher
    >
    169
    Wednesday, May 22, 13

    View Slide

  760. antisocial network
    170
    Wednesday, May 22, 13

    View Slide

  761. Ship it!
    antisocial network
    170
    Wednesday, May 22, 13

    View Slide

  762. Ship Shape
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  763. Ship Shape
    Good work so far
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  764. Ship Shape
    Good work so far
    People gonna flip out
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  765. Ship Shape
    Good work so far
    People gonna flip out
    Let’s tag a dev release
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  766. Ship Shape
    Good work so far
    People gonna flip out
    Let’s tag a dev release
    Bundle it up
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  767. Ship Shape
    Good work so far
    People gonna flip out
    Let’s tag a dev release
    Bundle it up
    And ship it
    antisocial network
    171
    Wednesday, May 22, 13

    View Slide

  768. You’re It
    >
    172
    Wednesday, May 22, 13

    View Slide

  769. ""sqitch"tag"v1.0.0*r1"*n"'Tag"v1.0.0*r1.'
    Tagged""change_pass""with"@v1.0.0*r1
    >
    You’re It
    >
    172
    Wednesday, May 22, 13

    View Slide

  770. ""sqitch"tag"v1.0.0*r1"*n"'Tag"v1.0.0*r1.'
    Tagged""change_pass""with"@v1.0.0*r1
    >
    ""git"commit"*am"'Tag"the"database"@v1.0.0*r1.'"""
    [master"6661268]"Tag"the"database"@v1.0.0*r1.
    "1"file"changed,"1"insertion(+)
    >
    You’re It
    >
    172
    Wednesday, May 22, 13

    View Slide

  771. ""git"tag"v1.0.0*r1"*am"'Tag"v1.0.0*r1.'
    >
    ""sqitch"tag"v1.0.0*r1"*n"'Tag"v1.0.0*r1.'
    Tagged""change_pass""with"@v1.0.0*r1
    >
    ""git"commit"*am"'Tag"the"database"@v1.0.0*r1.'"""
    [master"6661268]"Tag"the"database"@v1.0.0*r1.
    "1"file"changed,"1"insertion(+)
    >
    You’re It
    >
    In sync.
    In sync.
    172
    Wednesday, May 22, 13

    View Slide

  772. ""git"tag"v1.0.0*r1"*am"'Tag"v1.0.0*r1.'
    >
    ""sqitch"tag"v1.0.0*r1"*n"'Tag"v1.0.0*r1.'
    Tagged""change_pass""with"@v1.0.0*r1
    >
    ""git"commit"*am"'Tag"the"database"@v1.0.0*r1.'"""
    [master"6661268]"Tag"the"database"@v1.0.0*r1.
    "1"file"changed,"1"insertion(+)
    >
    ""git"push
    Counting"objects:"5,"done.
    Writing"objects:"100%"(3/3),"346"bytes,"done.
    Total"3"(delta"2),"reused"0"(delta"0)
    To"../flipr*remote
    """0e31da9..6661268""master"*>"master
    >
    You’re It
    >
    172
    Wednesday, May 22, 13

    View Slide

  773. ""git"tag"v1.0.0*r1"*am"'Tag"v1.0.0*r1.'
    >
    ""sqitch"tag"v1.0.0*r1"*n"'Tag"v1.0.0*r1.'
    Tagged""change_pass""with"@v1.0.0*r1
    >
    ""git"commit"*am"'Tag"the"database"@v1.0.0*r1.'"""
    [master"6661268]"Tag"the"database"@v1.0.0*r1.
    "1"file"changed,"1"insertion(+)
    >
    ""git"push
    Counting"objects:"5,"done.
    Writing"objects:"100%"(3/3),"346"bytes,"done.
    Total"3"(delta"2),"reused"0"(delta"0)
    To"../flipr*remote
    """0e31da9..6661268""master"*>"master
    >
    ""git"push"**tags
    To"../flipr*remote
    "*"[new"tag]"""""""""v1.0.0*r1"*>"v1.0.0*r1
    >
    You’re It
    >
    172
    Wednesday, May 22, 13

    View Slide

  774. Bundle Up
    >
    173
    Wednesday, May 22, 13

    View Slide

  775. ""sqitch"bundle"**dest*dir"flipr*1.0.0*r1
    Bundling"into"flipr*1.0.0*r1
    Writing"config
    Writing"plan
    Writing"scripts
    ""+"appschema
    ""+"users
    ""+"flips
    ""+"insert_user
    ""+"change_pass"@v1.0.0*r1
    >
    Bundle Up
    >
    173
    Wednesday, May 22, 13

    View Slide

  776. ""sqitch"bundle"**dest*dir"flipr*1.0.0*r1
    Bundling"into"flipr*1.0.0*r1
    Writing"config
    Writing"plan
    Writing"scripts
    ""+"appschema
    ""+"users
    ""+"flips
    ""+"insert_user
    ""+"change_pass"@v1.0.0*r1
    >
    Bundle Up
    >
    {
    173
    Wednesday, May 22, 13

    View Slide

  777. Bundled?
    >
    174
    Wednesday, May 22, 13

    View Slide

  778. >"cd"flipr*1.0.0*r1
    >
    Bundled?
    >
    174
    Wednesday, May 22, 13

    View Slide

  779. ""createdb"flipr_qa"
    >
    >"cd"flipr*1.0.0*r1
    >
    Bundled?
    >
    174
    Wednesday, May 22, 13

    View Slide

  780. ""createdb"flipr_qa"
    >
    >"cd"flipr*1.0.0*r1
    >
    Bundled?
    >
    ""sqitch"*d"flipr_qa"deploy
    Adding"metadata"tables"to"flipr_qa
    Deploying"changes"to"flipr_qa
    ""+"appschema"..............."ok
    ""+"users"..................."ok
    ""+"flips"..................."ok
    ""+"insert_user"@v1.0.0*r1".."ok
    >
    174
    Wednesday, May 22, 13

    View Slide

  781. ""createdb"flipr_qa"
    >
    >"cd"flipr*1.0.0*r1
    >
    Bundled?
    >
    Ship it!
    ""sqitch"*d"flipr_qa"deploy
    Adding"metadata"tables"to"flipr_qa
    Deploying"changes"to"flipr_qa
    ""+"appschema"..............."ok
    ""+"users"..................."ok
    ""+"flips"..................."ok
    ""+"insert_user"@v1.0.0*r1".."ok
    >
    174
    Wednesday, May 22, 13

    View Slide

  782. antisocial network
    Merge Madness
    175
    Wednesday, May 22, 13

    View Slide

  783. antisocial network
    Merge Madness
    Merge everything
    175
    Wednesday, May 22, 13

    View Slide

  784. antisocial network
    Merge Madness
    Merge everything
    Back to master
    175
    Wednesday, May 22, 13

    View Slide

  785. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    175
    Wednesday, May 22, 13

    View Slide

  786. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    flips
    175
    Wednesday, May 22, 13

    View Slide

  787. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    flips
    userfuncs
    175
    Wednesday, May 22, 13

    View Slide

  788. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    flips
    userfuncs
    Union merge sqitch.plan
    175
    Wednesday, May 22, 13

    View Slide

  789. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    flips
    userfuncs
    Union merge sqitch.plan
    Bundle and ship
    175
    Wednesday, May 22, 13

    View Slide

  790. antisocial network
    Merge Madness
    Merge everything
    Back to master
    users
    flips
    userfuncs
    Union merge sqitch.plan
    Bundle and ship
    https:/
    /github.com/
    theory/agile-flipr.git
    175
    Wednesday, May 22, 13

    View Slide

  791. Ruh-Roh
    >
    176
    Wednesday, May 22, 13

    View Slide

  792. Ruh-Roh
    >
    >"git"reset"**hard"reltag
    HEAD"is"now"at"6661268"Tag"the"database"@v1.0.0*r1.
    >
    176
    Wednesday, May 22, 13

    View Slide

  793. ""psql"*d"flipr_test"*c""
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|"""""""""""""password"""""""""""""
    **********+**********************************
    "foo""""""|"9695da4dd567a19f9b92065f240c6725
    "bar""""""|"9695da4dd567a19f9b92065f240c6725
    (2"rows)
    >
    Ruh-Roh
    >
    >"git"reset"**hard"reltag
    HEAD"is"now"at"6661268"Tag"the"database"@v1.0.0*r1.
    >
    Same
    password
    176
    Wednesday, May 22, 13

    View Slide

  794. ""psql"*d"flipr_test"*c""
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|"""""""""""""password"""""""""""""
    **********+**********************************
    "foo""""""|"9695da4dd567a19f9b92065f240c6725
    "bar""""""|"9695da4dd567a19f9b92065f240c6725
    (2"rows)
    >
    Ruh-Roh
    >
    >"git"reset"**hard"reltag
    HEAD"is"now"at"6661268"Tag"the"database"@v1.0.0*r1.
    >
    176
    Wednesday, May 22, 13

    View Slide

  795. ""psql"*d"flipr_test"*c""
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|"""""""""""""password"""""""""""""
    **********+**********************************
    "foo""""""|"9695da4dd567a19f9b92065f240c6725
    "bar""""""|"9695da4dd567a19f9b92065f240c6725
    (2"rows)
    >
    Ruh-Roh
    >
    Not good.
    >"git"reset"**hard"reltag
    HEAD"is"now"at"6661268"Tag"the"database"@v1.0.0*r1.
    >
    176
    Wednesday, May 22, 13

    View Slide

  796. PGCryptonite
    >
    177
    Wednesday, May 22, 13

    View Slide

  797. ""sqitch"add"pgcrypto"*n"'Loads"pgcrypto"extension.'
    Adding"deploy/pgcrypto.sql
    Adding"revert/pgcrypto.sql
    Adding"verify/pgcrypto.sql
    Added""pgcrypto""to"sqitch.plan
    >
    PGCryptonite
    >
    177
    Wednesday, May 22, 13

    View Slide

  798. ""sqitch"add"pgcrypto"*n"'Loads"pgcrypto"extension.'
    Adding"deploy/pgcrypto.sql
    Adding"revert/pgcrypto.sql
    Adding"verify/pgcrypto.sql
    Added""pgcrypto""to"sqitch.plan
    >
    PGCryptonite
    >
    ""emacs"deploy/pgcrpyto.sql
    >
    177
    Wednesday, May 22, 13

    View Slide

  799. deploy/pgcrypto
    deploy/pgcrypto.sql
    **"Deploy"pgcrypto
    BEGIN;
    COMMIT;
    **"XXX"Add"DDLs"here.
    178
    Wednesday, May 22, 13

    View Slide

  800. deploy/pgcrypto
    deploy/pgcrypto.sql
    **"Deploy"pgcrypto
    BEGIN;
    COMMIT;
    CREATE"EXTENSION"pgcrypto;
    178
    Wednesday, May 22, 13

    View Slide

  801. ""sqitch"add"pgcrypto"*n"'Loads"pgcrypto"extension.'
    Adding"deploy/pgcrypto.sql
    Adding"revert/pgcrypto.sql
    Adding"verify/pgcrypto.sql
    Added""pgcrypto""to"sqitch.plan
    >"emacs"deploy/pgcrpyto.sql
    >
    PGCryptonite
    >
    179
    Wednesday, May 22, 13

    View Slide

  802. ""sqitch"add"pgcrypto"*n"'Loads"pgcrypto"extension.'
    Adding"deploy/pgcrypto.sql
    Adding"revert/pgcrypto.sql
    Adding"verify/pgcrypto.sql
    Added""pgcrypto""to"sqitch.plan
    >"emacs"deploy/pgcrpyto.sql
    >
    PGCryptonite
    >
    ""emacs"verify/pgcrpyto.sql
    >
    179
    Wednesday, May 22, 13

    View Slide

  803. **"Verify"pgcrypto
    BEGIN;
    verify/pgcrypto
    verify/pgcrypto.sql
    **"XXX"Add"verifications"here.
    COMMIT;
    180
    Wednesday, May 22, 13

    View Slide

  804. **"Verify"pgcrypto
    BEGIN;
    verify/pgcrypto
    verify/pgcrypto.sql
    COMMIT;
    SELECT"1/count(*)"FROM"pg_extension"WHERE"extname"="'pgcrypto';
    SELECT"has_function_privilege('crypt(text,"text)',"'execute');
    SELECT"has_function_privilege('gen_salt(text)',"'execute');
    180
    Wednesday, May 22, 13

    View Slide

  805. **"Verify"pgcrypto
    BEGIN;
    verify/pgcrypto
    verify/pgcrypto.sql
    COMMIT;
    SELECT"1/count(*)"FROM"pg_extension"WHERE"extname"="'pgcrypto';
    SELECT"has_function_privilege('crypt(text,"text)',"'execute');
    SELECT"has_function_privilege('gen_salt(text)',"'execute');
    180
    Wednesday, May 22, 13

    View Slide

  806. **"Verify"pgcrypto
    BEGIN;
    verify/pgcrypto
    verify/pgcrypto.sql
    COMMIT;
    SELECT"1/count(*)"FROM"pg_extension"WHERE"extname"="'pgcrypto';
    SELECT"has_function_privilege('crypt(text,"text)',"'execute');
    SELECT"has_function_privilege('gen_salt(text)',"'execute');
    180
    Wednesday, May 22, 13

    View Slide

  807. You Know the Drill
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  808. You Know the Drill
    Write revert script
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  809. You Know the Drill
    Write revert script
    Add test
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  810. You Know the Drill
    Write revert script
    Add test
    Use has_function()
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  811. You Know the Drill
    Write revert script
    Add test
    Use has_function()
    Commit
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  812. You Know the Drill
    Write revert script
    Add test
    Use has_function()
    Commit
    Push
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  813. You Know the Drill
    Write revert script
    Add test
    Use has_function()
    Commit
    Push
    Modify the insert_user test
    antisocial network
    181
    Wednesday, May 22, 13

    View Slide

  814. >
    182
    Wednesday, May 22, 13

    View Slide

  815. ""git"diff"test/insert_user.sql
    @@"*5,7"+5,7"@@"SET"search_path"TO"flipr,public;
    "
    "**"Plan"the"tests.
    "BEGIN;
    *SELECT"plan(11);
    +SELECT"plan(12);
    "
    "SELECT"has_function("'insert_user'");
    "SELECT"has_function(
    @@"*29,25"+29,25"@@"SELECT"lives_ok(
    """""'Insert"a"user'
    ");
    "
    *SELECT"row_eq(
    *"""'SELECT"*"FROM"users',
    *"""ROW('theory',"md5('foo'),"NOW())::users,
    *"""'The"user"should"have"been"inserted'
    *);
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'theory'
    +"""""""AND"password"="crypt('foo',"password)
    +),"'The"user"should"have"been"inserted'");
    >
    182
    Wednesday, May 22, 13

    View Slide

  816. ""git"diff"test/insert_user.sql
    @@"*5,7"+5,7"@@"SET"search_path"TO"flipr,public;
    "
    "**"Plan"the"tests.
    "BEGIN;
    *SELECT"plan(11);
    +SELECT"plan(12);
    "
    "SELECT"has_function("'insert_user'");
    "SELECT"has_function(
    @@"*29,25"+29,25"@@"SELECT"lives_ok(
    """""'Insert"a"user'
    ");
    "
    *SELECT"row_eq(
    *"""'SELECT"*"FROM"users',
    *"""ROW('theory',"md5('foo'),"NOW())::users,
    *"""'The"user"should"have"been"inserted'
    *);
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'theory'
    +"""""""AND"password"="crypt('foo',"password)
    +),"'The"user"should"have"been"inserted'");
    >
    182
    Wednesday, May 22, 13

    View Slide

  817. ""git"diff"test/insert_user.sql
    @@"*5,7"+5,7"@@"SET"search_path"TO"flipr,public;
    "
    "**"Plan"the"tests.
    "BEGIN;
    *SELECT"plan(11);
    +SELECT"plan(12);
    "
    "SELECT"has_function("'insert_user'");
    "SELECT"has_function(
    @@"*29,25"+29,25"@@"SELECT"lives_ok(
    """""'Insert"a"user'
    ");
    "
    *SELECT"row_eq(
    *"""'SELECT"*"FROM"users',
    *"""ROW('theory',"md5('foo'),"NOW())::users,
    *"""'The"user"should"have"been"inserted'
    *);
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'theory'
    +"""""""AND"password"="crypt('foo',"password)
    +),"'The"user"should"have"been"inserted'");
    >
    182
    Wednesday, May 22, 13

    View Slide

  818. "SELECT"lives_ok(
    """""$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """""'Insert"another"user'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Both"users"should"be"present'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'There"should"be"two"users')
    +""FROM"flipr.users;
    +
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'strongrrl'
    +"""""""AND"password"="crypt('w00t',"password)
    +),"'The"second"user"should"have"been"inserted'");
    "SELECT"throws_ok(
    """""$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    183
    Wednesday, May 22, 13

    View Slide

  819. "SELECT"lives_ok(
    """""$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """""'Insert"another"user'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Both"users"should"be"present'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'There"should"be"two"users')
    +""FROM"flipr.users;
    +
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'strongrrl'
    +"""""""AND"password"="crypt('w00t',"password)
    +),"'The"second"user"should"have"been"inserted'");
    "SELECT"throws_ok(
    """""$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    183
    Wednesday, May 22, 13

    View Slide

  820. "SELECT"lives_ok(
    """""$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """""'Insert"another"user'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Both"users"should"be"present'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'There"should"be"two"users')
    +""FROM"flipr.users;
    +
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'strongrrl'
    +"""""""AND"password"="crypt('w00t',"password)
    +),"'The"second"user"should"have"been"inserted'");
    "SELECT"throws_ok(
    """""$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    183
    Wednesday, May 22, 13

    View Slide

  821. "SELECT"lives_ok(
    """""$$"SELECT"insert_user('strongrrl',"'w00t')"$$,
    """""'Insert"another"user'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Both"users"should"be"present'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'There"should"be"two"users')
    +""FROM"flipr.users;
    +
    +SELECT"ok("EXISTS(
    +""""SELECT"1"FROM"flipr.users
    +"""""WHERE"nickname"="'strongrrl'
    +"""""""AND"password"="crypt('w00t',"password)
    +),"'The"second"user"should"have"been"inserted'");
    "SELECT"throws_ok(
    """""$$"SELECT"insert_user('theory',"'ha*ha')"$$,
    183
    Wednesday, May 22, 13

    View Slide

  822. @@"*56,14"+56,8"@@"SELECT"throws_ok(
    """""'Should"get"an"error"for"duplicate"nickname'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Should"still"have"just"the"two"users'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'Should"still"have"two"users')
    +""FROM"flipr.users;
    "
    "SELECT"finish();
    "ROLLBACK;
    >
    184
    Wednesday, May 22, 13

    View Slide

  823. @@"*56,14"+56,8"@@"SELECT"throws_ok(
    """""'Should"get"an"error"for"duplicate"nickname'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Should"still"have"just"the"two"users'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'Should"still"have"two"users')
    +""FROM"flipr.users;
    "
    "SELECT"finish();
    "ROLLBACK;
    >
    184
    Wednesday, May 22, 13

    View Slide

  824. @@"*56,14"+56,8"@@"SELECT"throws_ok(
    """""'Should"get"an"error"for"duplicate"nickname'
    ");
    "
    *SELECT"bag_eq(
    *""""'SELECT"*"FROM"users',
    *""""$$"VALUES
    *""""""""('theory',""""md5('foo'),""NOW()),
    *""""""""('strongrrl',"md5('w00t'),"NOW())
    *""""$$,
    *""""'Should"still"have"just"the"two"users'
    *);
    +SELECT"is(COUNT(*)::INT,"2,"'Should"still"have"two"users')
    +""FROM"flipr.users;
    "
    "SELECT"finish();
    "ROLLBACK;
    >
    184
    Wednesday, May 22, 13

    View Slide

  825. FAIL
    >
    185
    Wednesday, May 22, 13

    View Slide

  826. FAIL
    >"pg_prove"*d"flipr_test"test/insert_user.sql
    test/insert_user.sql".."1/12"
    #"Failed"test"7:""The"user"should"have"been"inserted"
    #"Failed"test"10:""The"second"user"should"have"been"inserted"
    #"Looks"like"you"failed"2"tests"of"12
    test/insert_user.sql".."Failed"2/12"subtests"
    Test"Summary"Report
    *******************
    test/insert_user.sql"(Wstat:"0"Tests:"12"Failed:"2)
    ""Failed"tests:""7,"10
    Files=1,"Tests=12,""1"wallclock"secs
    Result:"FAIL
    >
    >
    185
    Wednesday, May 22, 13

    View Slide

  827. FAIL
    >"pg_prove"*d"flipr_test"test/insert_user.sql
    test/insert_user.sql".."1/12"
    #"Failed"test"7:""The"user"should"have"been"inserted"
    #"Failed"test"10:""The"second"user"should"have"been"inserted"
    #"Looks"like"you"failed"2"tests"of"12
    test/insert_user.sql".."Failed"2/12"subtests"
    Test"Summary"Report
    *******************
    test/insert_user.sql"(Wstat:"0"Tests:"12"Failed:"2)
    ""Failed"tests:""7,"10
    Files=1,"Tests=12,""1"wallclock"secs
    Result:"FAIL
    >
    >
    As expected.
    185
    Wednesday, May 22, 13

    View Slide

  828. Back when discussing
    traditional migration
    systems, I said…
    antisocial network
    186
    Wednesday, May 22, 13

    View Slide

  829. Managing
    procedures
    is a PITA!
    antisocial network
    187
    Wednesday, May 22, 13

    View Slide

  830. Consider this Change
    >
    188
    Wednesday, May 22, 13

    View Slide

  831. Consider this Change
    ""git"diff
    diff"**git"a/deploy/insert_user.sql"b/deploy/insert_user.sql
    index"eb30fed..5c28d02"100644
    ***"a/deploy/insert_user.sql
    +++"b/deploy/insert_user.sql
    @@"*8,7"+8,7"@@"CREATE"OR"REPLACE"FUNCTION"flipr.insert_user(
    """""nickname"TEXT,
    """""password"TEXT
    ")"RETURNS"VOID"LANGUAGE"SQL"SECURITY"DEFINER"AS"$$
    *""""INSERT"INTO"flipr.users"VALUES($1,"md5($2));
    +""""INSERT"INTO"flipr.users"values($1,"crypt($2,"gen_salt('md5')));
    "$$;
    "
    "COMMIT;
    >
    188
    Wednesday, May 22, 13

    View Slide

  832. Consider this Change
    ""git"diff
    diff"**git"a/deploy/insert_user.sql"b/deploy/insert_user.sql
    index"eb30fed..5c28d02"100644
    ***"a/deploy/insert_user.sql
    +++"b/deploy/insert_user.sql
    @@"*8,7"+8,7"@@"CREATE"OR"REPLACE"FUNCTION"flipr.insert_user(
    """""nickname"TEXT,
    """""password"TEXT
    ")"RETURNS"VOID"LANGUAGE"SQL"SECURITY"DEFINER"AS"$$
    *""""INSERT"INTO"flipr.users"VALUES($1,"md5($2));
    +""""INSERT"INTO"flipr.users"values($1,"crypt($2,"gen_salt('md5')));
    "$$;
    "
    "COMMIT;
    >
    Simple, right?
    188
    Wednesday, May 22, 13

    View Slide

  833. Not So Much
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  834. Not So Much
    Copy insert_user.sql to new deploy file
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  835. Not So Much
    Copy insert_user.sql to new deploy file
    Change that new file
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  836. Not So Much
    Copy insert_user.sql to new deploy file
    Change that new file
    Copy insert_user.sql to new revert file
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  837. Not So Much
    Copy insert_user.sql to new deploy file
    Change that new file
    Copy insert_user.sql to new revert file
    Test it
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  838. Not So Much
    Copy insert_user.sql to new deploy file
    Change that new file
    Copy insert_user.sql to new revert file
    Test it
    Do the same for change_pass.sql
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  839. Not So Much
    Copy insert_user.sql to new deploy file
    Change that new file
    Copy insert_user.sql to new revert file
    Test it
    Do the same for change_pass.sql
    The problem with that…
    antisocial network
    189
    Wednesday, May 22, 13

    View Slide

  840. >
    190
    Wednesday, May 22, 13

    View Slide

  841. >"git"diff"HEAD^
    diff"**git"a/deploy/insert_user_crypt.sql"b/deploy/insert_user_crypto.sql
    new"file"mode"100644
    index"0000000..fa8d0c6
    ***"/dev/null
    +++"b/deploy/insert_user_crypt.sql
    @@"*0,0"+1,8"@@
    +**"requires:"users,"appuser,"pgcrypto
    +
    +CREATE"OR"REPLACE"FUNCTION"insert_user(
    +""""nickname"TEXT,
    +""""password"TEXT
    +)"RETURNS"VOID"LANGUAGE"SQL"AS"$$
    +""""INSERT"INTO"users"values($1,"crypt($2,"gen_salt('md5')));
    +$$;
    diff"**git"a/revert/insert_user_crypt.sql"b/revert/insert_user_crypto.sql
    new"file"mode"100644
    index"0000000..a7f4e31
    ***"/dev/null
    +++"b/revert/insert_user_crypt.sql
    @@"*0,0"+1,8"@@
    +**"requires:"users,"appuser
    +
    +CREATE"OR"REPLACE"FUNCTION"insert_user(
    +""""nickname"TEXT,
    +""""password"TEXT
    +)"RETURNS"VOID"LANGUAGE"SQL"AS"$$
    +""""INSERT"INTO"users"values($1,"md5($2));
    +$$;
    >
    190
    Wednesday, May 22, 13

    View Slide

  842. >"git"diff"HEAD^
    diff"**git"a/deploy/insert_user_crypt.sql"b/deploy/insert_user_crypto.sql
    new"file"mode"100644
    index"0000000..fa8d0c6
    ***"/dev/null
    +++"b/deploy/insert_user_crypt.sql
    @@"*0,0"+1,8"@@
    +**"requires:"users,"appuser,"pgcrypto
    +
    +CREATE"OR"REPLACE"FUNCTION"insert_user(
    +""""nickname"TEXT,
    +""""password"TEXT
    +)"RETURNS"VOID"LANGUAGE"SQL"AS"$$
    +""""INSERT"INTO"users"values($1,"crypt($2,"gen_salt('md5')));
    +$$;
    diff"**git"a/revert/insert_user_crypt.sql"b/revert/insert_user_crypto.sql
    new"file"mode"100644
    index"0000000..a7f4e31
    ***"/dev/null
    +++"b/revert/insert_user_crypt.sql
    @@"*0,0"+1,8"@@
    +**"requires:"users,"appuser
    +
    +CREATE"OR"REPLACE"FUNCTION"insert_user(
    +""""nickname"TEXT,
    +""""password"TEXT
    +)"RETURNS"VOID"LANGUAGE"SQL"AS"$$
    +""""INSERT"INTO"users"values($1,"md5($2));
    +$$;
    >
    Oy.
    190
    Wednesday, May 22, 13

    View Slide

  843. Let Sqitch do the work.
    antisocial network
    191
    Wednesday, May 22, 13

    View Slide

  844. Rework It
    >
    192
    Wednesday, May 22, 13

    View Slide

  845. ""sqitch"rework"insert_user"*r"pgcrypto"\
    ""*n"'Changes"insert_user"to"use"pgcrypto.'
    Added""insert_user"[[email protected]*r1"pgcrypto]""to"
    sqitch.plan.
    Modify"these"files"as"appropriate:
    ""*"deploy/insert_user.sql
    ""*"revert/insert_user.sql
    ""*"verify/insert_user.sql
    >
    Rework It
    >
    192
    Wednesday, May 22, 13

    View Slide

  846. ""sqitch"rework"insert_user"*r"pgcrypto"\
    ""*n"'Changes"insert_user"to"use"pgcrypto.'
    Added""insert_user"[[email protected]*r1"pgcrypto]""to"
    sqitch.plan.
    Modify"these"files"as"appropriate:
    ""*"deploy/insert_user.sql
    ""*"revert/insert_user.sql
    ""*"verify/insert_user.sql
    >
    Rework It
    >
    192
    Wednesday, May 22, 13

    View Slide

  847. ""sqitch"rework"insert_user"*r"pgcrypto"\
    ""*n"'Changes"insert_user"to"use"pgcrypto.'
    Added""insert_user"[[email protected]*r1"pgcrypto]""to"
    sqitch.plan.
    Modify"these"files"as"appropriate:
    ""*"deploy/insert_user.sql
    ""*"revert/insert_user.sql
    ""*"verify/insert_user.sql
    >
    Rework It
    >
    192
    Wednesday, May 22, 13

    View Slide

  848. ""sqitch"rework"insert_user"*r"pgcrypto"\
    ""*n"'Changes"insert_user"to"use"pgcrypto.'
    Added""insert_user"[[email protected]*r1"pgcrypto]""to"
    sqitch.plan.
    Modify"these"files"as"appropriate:
    ""*"deploy/insert_user.sql
    ""*"revert/insert_user.sql
    ""*"verify/insert_user.sql
    >
    Rework It
    >
    Same files?
    192
    Wednesday, May 22, 13

    View Slide

  849. Same Files?
    >
    193
    Wednesday, May 22, 13

    View Slide

  850. ""git"status
    #"On"branch"master
    #"Changes"not"staged"for"commit:
    #"""(use""git"add"...""to"update"what"will"be"committe
    #"""(use""git"checkout"**"...""to"discard"changes"in"w
    #
    #" modified:"""revert/insert_user.sql
    #" modified:"""sqitch.plan
    #" modified:"""test/insert_user.sql
    #
    #"Untracked"files:
    #"""(use""git"add"...""to"include"in"what"will"be"comm
    #
    #" deploy/[email protected]*r1.sql
    #" revert/[email protected]*r1.sql
    #" verify/[email protected]*r1.sql
    no"changes"added"to"commit"(use""git"add""and/or""git"commit
    >
    Same Files?
    >
    193
    Wednesday, May 22, 13

    View Slide

  851. ""git"status
    #"On"branch"master
    #"Changes"not"staged"for"commit:
    #"""(use""git"add"...""to"update"what"will"be"committe
    #"""(use""git"checkout"**"...""to"discard"changes"in"w
    #
    #" modified:"""revert/insert_user.sql
    #" modified:"""sqitch.plan
    #" modified:"""test/insert_user.sql
    #
    #"Untracked"files:
    #"""(use""git"add"...""to"include"in"what"will"be"comm
    #
    #" deploy/[email protected]*r1.sql
    #" revert/[email protected]*r1.sql
    #" verify/[email protected]*r1.sql
    no"changes"added"to"commit"(use""git"add""and/or""git"commit
    >
    Same Files?
    >
    193
    Wednesday, May 22, 13

    View Slide

  852. ""git"status
    #"On"branch"master
    #"Changes"not"staged"for"commit:
    #"""(use""git"add"...""to"update"what"will"be"committe
    #"""(use""git"checkout"**"...""to"discard"changes"in"w
    #
    #" modified:"""revert/insert_user.sql
    #" modified:"""sqitch.plan
    #" modified:"""test/insert_user.sql
    #
    #"Untracked"files:
    #"""(use""git"add"...""to"include"in"what"will"be"comm
    #
    #" deploy/[email protected]*r1.sql
    #" revert/[email protected]*r1.sql
    #" verify/[email protected]*r1.sql
    no"changes"added"to"commit"(use""git"add""and/or""git"commit
    >
    Same Files?
    >
    As of
    @v1.0.0-r1
    193
    Wednesday, May 22, 13

    View Slide

  853. ""git"status
    #"On"branch"master
    #"Changes"not"staged"for"commit:
    #"""(use""git"add"...""to"update"what"will"be"committe
    #"""(use""git"checkout"**"...""to"discard"changes"in"w
    #
    #" modified:"""revert/insert_user.sql
    #" modified:"""sqitch.plan
    #" modified:"""test/insert_user.sql
    #
    #"Untracked"files:
    #"""(use""git"add"...""to"include"in"what"will"be"comm
    #
    #" deploy/[email protected]*r1.sql
    #" revert/[email protected]*r1.sql
    #" verify/[email protected]*r1.sql
    no"changes"added"to"commit"(use""git"add""and/or""git"commit
    >
    Same Files?
    >
    193
    Wednesday, May 22, 13

    View Slide

  854. ""git"status
    #"On"branch"master
    #"Changes"not"staged"for"commit:
    #"""(use""git"add"...""to"update"what"will"be"committe
    #"""(use""git"checkout"**"...""to"discard"changes"in"w
    #
    #" modified:"""revert/insert_user.sql
    #" modified:"""sqitch.plan
    #" modified:"""test/insert_user.sql
    #
    #"Untracked"files:
    #"""(use""git"add"...""to"include"in"what"will"be"comm
    #
    #" deploy/[email protected]*r1.sql
    #" revert/[email protected]*r1.sql
    #" verify/[email protected]*r1.sql
    no"changes"added"to"commit"(use""git"add""and/or""git"commit
    >
    Same Files?
    >
    Previous deploy
    becomes revert
    193
    Wednesday, May 22, 13

    View Slide

  855. What’s the Diff?
    >
    194
    Wednesday, May 22, 13

    View Slide

  856. What’s the Diff?
    ""diff"*u"deploy/insert_user.sql
    diff"**git"a/deploy/insert_user.sql"b/deploy/insert_user.sql
    @@"*1,6"+1,7"@@
    "**"Deploy"insert_user
    "**"requires:"users
    "**"requires:"appschema
    +**"requires:"appschema
    "
    "BEGIN;
    "
    @@"*8,7"+9,7"@@"CREATE"OR"REPLACE"FUNCTION"flipr.insert_user(
    """""nickname"TEXT,
    """""password"TEXT
    ")"RETURNS"VOID"LANGUAGE"SQL"SECURITY"DEFINER"AS"$$
    *""""INSERT"INTO"flipr.users"VALUES($1,"md5($2));
    +""""INSERT"INTO"flipr.users"values($1,"crypt($2,"gen_salt('md5')));
    "$$;
    "
    "COMMIT;
    >
    >
    194
    Wednesday, May 22, 13

    View Slide

  857. Send it Up!
    >
    195
    Wednesday, May 22, 13

    View Slide

  858. Send it Up!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    >
    195
    Wednesday, May 22, 13

    View Slide

  859. >"psql"*d"flipr_test"*c""
    """"DELETE"FROM"flipr.users;
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|""""""""""""""password""""""""""""""
    **********+************************************
    "foo""""""|"$1$nKO47p03$YRXYTt4NoNncTThLyxzEq1
    "bar""""""|"$1$LbVUs/p.$LVbvPlkD8rJlixW2nS3WP0
    (2"rows)
    >
    Send it Up!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    >
    195
    Wednesday, May 22, 13

    View Slide

  860. >"psql"*d"flipr_test"*c""
    """"DELETE"FROM"flipr.users;
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|""""""""""""""password""""""""""""""
    **********+************************************
    "foo""""""|"$1$nKO47p03$YRXYTt4NoNncTThLyxzEq1
    "bar""""""|"$1$LbVUs/p.$LVbvPlkD8rJlixW2nS3WP0
    (2"rows)
    >
    Send it Up!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    >
    \o/
    195
    Wednesday, May 22, 13

    View Slide

  861. Can We Go Back?
    >
    196
    Wednesday, May 22, 13

    View Slide

  862. Can We Go Back?
    >"sqitch"revert"**to"@HEAD^"*y
    ""*"insert_user".."ok
    >
    >
    196
    Wednesday, May 22, 13

    View Slide

  863. ""psql"*d"flipr_test"*c""
    """"DELETE"FROM"flipr.users;
    """"SELECT"flipr.insert_user('foo',"'secr3t'),
    """""""""""flipr.insert_user('bar',"'secr3t');
    """"SELECT"nickname,"password"FROM"flipr.users;
    "
    "nickname"|"""""""""""""password"""""""""""""
    **********+**********************************
    "foo""""""|"9695da4dd567a19f9b92065f240c6725
    "bar""""""|"9695da4dd567a19f9b92065f240c6725
    (2"rows)
    Can We Go Back?
    >"sqitch"revert"**to"@HEAD^"*y
    ""*"insert_user".."ok
    >
    >
    196
    Wednesday, May 22, 13

    View Slide

  864. Verify How?
    >
    197
    Wednesday, May 22, 13

    View Slide

  865. Verify How?
    >"emacs"verify/insert_user.sql
    >
    >
    197
    Wednesday, May 22, 13

    View Slide

  866. **"Verify"insert_user
    BEGIN;
    SELECT"has_function_privilege(
    """"'flipr.insert_user(text,"text)',
    """"'execute'
    );
    verify/insert_u
    verify/insert_user.sql
    COMMIT;
    198
    Wednesday, May 22, 13

    View Slide

  867. SELECT"1/COUNT(*)
    ""FROM"pg_catalog.pg_proc
    "WHERE"proname"="'insert_user'
    """AND"pg_get_functiondef(oid)
    """""""LIKE"$$%crypt($2,"gen_salt('md5'))%$$;
    **"Verify"insert_user
    BEGIN;
    SELECT"has_function_privilege(
    """"'flipr.insert_user(text,"text)',
    """"'execute'
    );
    verify/insert_u
    verify/insert_user.sql
    COMMIT;
    198
    Wednesday, May 22, 13

    View Slide

  868. SELECT"1/COUNT(*)
    ""FROM"pg_catalog.pg_proc
    "WHERE"proname"="'insert_user'
    """AND"pg_get_functiondef(oid)
    """""""LIKE"$$%crypt($2,"gen_salt('md5'))%$$;
    **"Verify"insert_user
    BEGIN;
    SELECT"has_function_privilege(
    """"'flipr.insert_user(text,"text)',
    """"'execute'
    );
    verify/insert_u
    verify/insert_user.sql
    COMMIT;
    Yeah,
    compare
    source.
    198
    Wednesday, May 22, 13

    View Slide

  869. >"emacs"verify/insert_user.sql
    >
    Let’s Go!
    199
    Wednesday, May 22, 13

    View Slide

  870. >"emacs"verify/insert_user.sql
    >
    Let’s Go!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    199
    Wednesday, May 22, 13

    View Slide

  871. >"emacs"verify/insert_user.sql
    >
    Let’s Go!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    >"psql"*d"flipr_test"*c"'DELETE"FROM"flipr.users'
    DELETE"2
    >
    199
    Wednesday, May 22, 13

    View Slide

  872. >"emacs"verify/insert_user.sql
    >
    Let’s Go!
    >"sqitch"deploy
    Deploying"changes"to"flipr_test
    ""+"insert_user".."ok
    >
    >"psql"*d"flipr_test"*c"'DELETE"FROM"flipr.users'
    DELETE"2
    >
    pg_prove"*d"flipr_test"test/insert_user.sql""""
    test/insert_user.sql".."ok"""""
    All"tests"successful.
    Files=1,"Tests=12,""0"wallclock"secs
    Result:"PASS
    >
    Shazam!
    199
    Wednesday, May 22, 13

    View Slide

  873. Add, Commit, Push, Go
    >
    200
    Wednesday, May 22, 13

    View Slide

  874. ""git"add".
    >"git"commit"*m"'Update"insert_user"to"use"pgcrypto.'
    [master"59f5823]"Update"insert_user"to"use"pgcrypto.
    "8"files"changed,"66"insertions(+),"25"deletions(*)
    "create"mode"100644"deploy/[email protected]*r1.sql
    "create"mode"100644"revert/[email protected]*r1.sql
    "create"mode"100644"verify/[email protected]*r1.sql
    >
    Add, Commit, Push, Go
    >
    200
    Wednesday, May 22, 13

    View Slide

  875. ""git"add".
    >"git"commit"*m"'Update"insert_user"to"use"pgcrypto.'
    [master"59f5823]"Update"insert_user"to"use"pgcrypto.
    "8"files"changed,"66"insertions(+),"25"deletions(*)
    "create"mode"100644"deploy/[email protected]*r1.sql
    "create"mode"100644"revert/[email protected]*r1.sql
    "create"mode"100644"verify/[email protected]*r1.sql
    >
    Add, Commit, Push, Go
    >"git"push
    Counting"objects:"17,"done.
    Delta"compression"using"up"to"4"threads.
    Compressing"objects:"100%"(10/10),"done.
    Writing"objects:"100%"(10/10),"1.75"KiB,"done.
    Total"10"(delta"6),"reused"0"(delta"0)
    To"../flipr*remote
    """5f4c29a..59f5823""master"*>"master
    >
    >
    200
    Wednesday, May 22, 13

    View Slide

  876. antisocial network
    Change It Up
    201
    Wednesday, May 22, 13

    View Slide

  877. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    201
    Wednesday, May 22, 13

    View Slide

  878. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    Rework change_pass
    201
    Wednesday, May 22, 13

    View Slide

  879. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    Rework change_pass
    Use pgcrypo
    201
    Wednesday, May 22, 13

    View Slide

  880. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    Rework change_pass
    Use pgcrypo
    Test first!
    201
    Wednesday, May 22, 13

    View Slide

  881. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    Rework change_pass
    Use pgcrypo
    Test first!
    Bundle, tag, release
    201
    Wednesday, May 22, 13

    View Slide

  882. antisocial network
    Change It Up
    git reset --hard
    insert_user2
    Rework change_pass
    Use pgcrypo
    Test first!
    Bundle, tag, release
    https:/
    /github.com/
    theory/agile-flipr.git
    201
    Wednesday, May 22, 13

    View Slide

  883. I’m afraid I have some
    bad news…
    antisocial network
    202
    Wednesday, May 22, 13

    View Slide

  884. 203
    Wednesday, May 22, 13

    View Slide

  885. Antisocial Networking Startup Flipr Heads To
    The Deadpool
    by Michael Arrington on November 2, 2010
    antisocial network
    I loved this site.
    Flipr, an online “antisocial networking” site that encouraged users to alienate
    each other in order to increase their antisocial cred, is shutting down. The
    startup’s homepage now consists of a letter to Flipr users instructing them to
    download their “flips” by November 30, at which point nearly all of the
    service’s features will be taken offline and data deleted.
    In the letter, Flipr CEO David Wheeler writes that despite ample venture funding and a dedicated
    team of database developers, the site underestimated people’s willingness to be assholes. This is
    not something I can relate to, although from what I’ve been told by more polite society, it is
    indeed the case. Such a shame.
    203
    Wednesday, May 22, 13

    View Slide

  886. I’m afraid it’s true.
    antisocial network
    RIP
    204
    Wednesday, May 22, 13

    View Slide

  887. I’m sorry I have no money
    left to pay you.
    antisocial network
    RIP
    205
    Wednesday, May 22, 13

    View Slide

  888. I hope you enjoyed
    working here.
    antisocial network
    RIP
    206
    Wednesday, May 22, 13

    View Slide

  889. And that you’re able to
    use the skills you’ve
    gained in your next job.
    antisocial network
    RIP
    207
    Wednesday, May 22, 13

    View Slide

  890. Git Skillz
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  891. Git Skillz
    Branching
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  892. Git Skillz
    Branching
    Diffing
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  893. Git Skillz
    Branching
    Diffing
    Rebasing
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  894. Git Skillz
    Branching
    Diffing
    Rebasing
    Merging
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  895. Git Skillz
    Branching
    Diffing
    Rebasing
    Merging
    Committing
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  896. Git Skillz
    Branching
    Diffing
    Rebasing
    Merging
    Committing
    Pushing
    antisocial network
    RIP
    208
    Wednesday, May 22, 13

    View Slide

  897. MOAR Git
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  898. MOAR Git
    Bisecting
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  899. MOAR Git
    Bisecting
    Blaming
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  900. MOAR Git
    Bisecting
    Blaming
    Pull requests
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  901. MOAR Git
    Bisecting
    Blaming
    Pull requests
    Submitting patches
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  902. MOAR Git
    Bisecting
    Blaming
    Pull requests
    Submitting patches
    Rewriting history
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  903. MOAR Git
    Bisecting
    Blaming
    Pull requests
    Submitting patches
    Rewriting history
    Log formatting
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  904. MOAR Git
    Bisecting
    Blaming
    Pull requests
    Submitting patches
    Rewriting history
    Log formatting
    git help --all
    antisocial network
    RIP
    209
    Wednesday, May 22, 13

    View Slide

  905. pgTAP Skillz
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  906. pgTAP Skillz
    TDDD
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  907. pgTAP Skillz
    TDDD
    Schema testing
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  908. pgTAP Skillz
    TDDD
    Schema testing
    Scalar testing
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  909. pgTAP Skillz
    TDDD
    Schema testing
    Scalar testing
    Functional testing
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  910. pgTAP Skillz
    TDDD
    Schema testing
    Scalar testing
    Functional testing
    Relational testing
    antisocial network
    RIP
    210
    Wednesday, May 22, 13

    View Slide

  911. MOAR pgTAP
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  912. MOAR pgTAP
    Testing privileges
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  913. MOAR pgTAP
    Testing privileges
    Mocking interfaces
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  914. MOAR pgTAP
    Testing privileges
    Mocking interfaces
    Custom test functions
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  915. MOAR pgTAP
    Testing privileges
    Mocking interfaces
    Custom test functions
    xUnit-style testing
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  916. MOAR pgTAP
    Testing privileges
    Mocking interfaces
    Custom test functions
    xUnit-style testing
    Tests maintained in functions
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  917. MOAR pgTAP
    Testing privileges
    Mocking interfaces
    Custom test functions
    xUnit-style testing
    Tests maintained in functions
    http:/
    /pgtap.org/documentation.html
    antisocial network
    RIP
    211
    Wednesday, May 22, 13

    View Slide

  918. Sqitch Skillz
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  919. Sqitch Skillz
    Adding changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  920. Sqitch Skillz
    Adding changes
    Dependency management
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  921. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  922. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    Verifying changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  923. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    Verifying changes
    Reverting changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  924. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    Verifying changes
    Reverting changes
    Rebasing changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  925. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    Verifying changes
    Reverting changes
    Rebasing changes
    Reworking changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  926. Sqitch Skillz
    Adding changes
    Dependency management
    Deploying changes
    Verifying changes
    Reverting changes
    Rebasing changes
    Reworking changes
    antisocial network
    RIP
    212
    Wednesday, May 22, 13

    View Slide

  927. MOAR Sqitch
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  928. MOAR Sqitch
    Cross-project dependencies
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  929. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  930. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  931. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    Checkout command
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  932. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    Checkout command
    Reverts to last common change
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  933. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    Checkout command
    Reverts to last common change
    Changes Git branch
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  934. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    Checkout command
    Reverts to last common change
    Changes Git branch
    Deploys
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  935. MOAR Sqitch
    Cross-project dependencies
    Multiple projects, one database
    Changing Branches
    Checkout command
    Reverts to last common change
    Changes Git branch
    Deploys
    sqitch help
    antisocial network
    RIP
    213
    Wednesday, May 22, 13

    View Slide

  936. Good luck out there.
    antisocial network
    RIP
    214
    Wednesday, May 22, 13

    View Slide

  937. Agile
    Database Development
    David E. Wheeler
    PGCon 2013
    Ottawa
    Text: Attribution-Noncommercial-Share Alike 3.0 United States:
    http:/
    /creativecommons.org/licenses/by-nc-sa/3.0/us/
    Images licensed independently and © Their respective owners.
    iovation
    215
    Wednesday, May 22, 13

    View Slide