$30 off During Our Annual Pro Sale. View Details »

Branch in Time

Branch in Time

Full talk: https://tekin.co.uk/2019/02/a-talk-about-revision-histories

In one timeline a quick path to clarity. In the other a painful journey trying to uncover the obscure intent of a line of code. The only difference between these two realities? The revision history…

This is a story about revision histories and their impact on software maintainability. Think Sliding Doors, but with more Git!

Tekin Suleyman

November 15, 2018
Tweet

More Decks by Tekin Suleyman

Other Decks in Programming

Transcript

  1. Branch in Time
    A story about revision histories
    @tekin

    View Slide

  2. Docs-R-Us
    Seema

    View Slide

  3. Seema Docs-R-Us

    View Slide

  4. class PatientsController < ApplicationController
    before_action :load_doctor
    def index
    @patients = sorted_patients
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def sorted_patients
    @doctor.patients.sort { |patient| patient.name }
    end
    def load_doctor
    @doctor = doctor_from_current_session

    View Slide

  5. class PatientsController < ApplicationController
    before_action :load_doctor
    def index
    @patients = sorted_patients
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def sorted_patients
    @doctor.patients.sort { |patient| patient.name }
    end
    def load_doctor
    @doctor = doctor_from_current_session

    View Slide

  6. class PatientsController < ApplicationController
    before_action :load_doctor
    def index
    @patients = sorted_patients
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def sorted_patients
    @doctor.patients.order(:name)
    end
    def load_doctor
    @doctor = doctor_from_current_session

    View Slide

  7. class PatientsController < ApplicationController
    before_action :load_doctor
    def index
    @patients = sorted_patients
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def sorted_patients
    @doctor.patients.order(:name)
    end
    def load_doctor
    @doctor = doctor_from_current_session
    $ rake
    Run options: --seed 45260
    # Running:
    ....................................................................
    ....................................................................
    ....................................................................
    ....................................
    Finished in 123.299088s, 23.8629 runs/s, 34.6397 assertions/s.
    3311 runs, 45124 assertions, 0 failures, 0 errors, 0 skips

    View Slide

  8. class Patient < ApplicationRecord
    has_many :appointments
    validates_presence_of :name, :address, :date_of_birth
    end
    class Doctor < ApplicationRecord
    has_many :appointments
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end

    View Slide

  9. Git Fu
    1. git blame

    View Slide

  10. $ git blame app/controllers/patients_controller.rb
    Git Fu: git blame

    View Slide

  11. 3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 1) # Controller for listing a doctor's pa
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 2) class PatientsController < Application
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 3) before_filter :load_doctor
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 4)
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 5) def index
    6047246d (Josie P 2010-10-29 09:32:25 +0100 6) @patients = sorted_patients
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 7) end
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 8)
    9598514f (Josie P 2010-06-28 17:03:21 +0100 9) def show
    9598514f (Josie P 2010-06-28 17:03:21 +0100 10) @patient = @doctor.patients.find(p
    9598514f (Josie P 2010-06-28 17:03:21 +0100 11) end
    9598514f (Richard E 2010-06-28 17:03:21 +0100 12)
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 13) private
    dbdd0fb9 (Josie P 2010-10-29 09:31:52 +0100 18)
    6047246d (Josie P 2010-10-29 09:32:25 +0100 19) def sorted_patients
    dbdd0fb9 (Josie P 2010-10-29 09:31:52 +0100 20) @doctor.patients.sort {|patient| p
    dbdd0f69 (Josie P 2010-10-29 09:31:52 +0100 21) end
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 14)
    $ git blame app/controllers/patients_controller.rb
    Git Fu: git blame

    View Slide

  12. --patch
    Git Fu: git blame
    $ git log dbdd0fb9

    View Slide

  13. $ git log dbdd0fb9 --patch
    commit dbdd0fb9e870b91e6925903553f07df3becc9414
    Author: Josie Pickford
    Date: Fri Oct 29 09:31:52 2010 +0100
    PR Feedback: Fixed a typo
    diff --git a/app/controllers/patients_controller.rb b/app/controllers/patients_controller
    index d7c6df5..1e3debb 100644
    --- a/app/controllers/patients_controller.rb
    +++ b/app/controllers/patients_controller.rb
    @@ -13,7 +13,7 @@ class PatientsController < ApplicationController
    private
    def sorted_patients
    - @doctor.patients.sort {|pateint| pateint.name }
    + @doctor.patients.sort {|patient| patient.name }
    end
    Git Fu: git blame

    View Slide

  14. Git Fu
    1. git blame
    2. git log -S (AKA The Pickaxe)

    View Slide

  15. Git Fu: git log -S (AKA The Pickaxe)
    $ git log -S "sorted_patients" --patch --reverse

    View Slide

  16. Git Fu: git log -S (AKA The Pickaxe)
    $ git log -S "sorted_patients" --patch --reverse
    commit 23b6e0c6a9a7a392c312d4f0c51153e0769ebffc
    Author: Josie Pickford
    Date: Thurs Oct 28 17:55:32 2010 +0100
    Rename method
    diff --git a/app/controllers/patients_controller.rb b/app/controllers/
    patients_controller.rb
    index 51fbd8a..d7c6df5 100644
    --- a/app/controllers/patients_controller.rb
    +++ b/app/controllers/patients_controller.rb
    @@ -3,7 +3,7 @@ class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    - @patients = load_patients
    + @patients = sorted_patients
    end

    View Slide

  17. Git Fu
    1. git blame
    2. git log -S (AKA The Pickaxe)
    3. Pickaxe Round 2

    View Slide

  18. Git Fu: Pickaxe Round 2
    $ git log -S "load_patients" --patch --reverse
    commit 66f95816017b1c6582034d074333fa18884ad3c3
    Author: Josie Pickford
    Date: Thurs Oct 28 17:00:43 2010 +0100
    Fix patient ordering bug
    diff --git a/app/controllers/patients_controller.rb b/app/controllers/patients_controller
    index cb0e69c..51fbd8a 100644
    --- a/app/controllers/patients_controller.rb
    +++ b/app/controllers/patients_controller.rb
    @@ -3,7 +3,7 @@ class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    - @patients = @doctor.patients.order(:name)
    + @patients = load_patients
    end

    View Slide

  19. Git Fu
    1. git blame
    2. git log -S (AKA The Pickaxe)
    3. Pickaxe Round 2
    4. Find the Pull Request

    View Slide

  20. Git Fu: Find the Pull Request

    View Slide

  21. Git Fu: Find the Pull Request

    View Slide

  22. Git Fu: Find the Pull Request

    View Slide

  23. Git Fu: Find the Pull Request

    View Slide

  24. View Slide

  25. 8 years ago...

    View Slide

  26. Docs-R-Us
    Josie
    8 years ago...

    View Slide

  27. Doh!

    8 years ago...
    Josie

    View Slide

  28. Y U NO ALPHABETICAL!?

    View Slide

  29. class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    @patients = @doctor.patients.order(:name)
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def load_doctor
    @doctor = doctor_from_current_session
    end
    end

    View Slide

  30. class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    @patients = @doctor.patients.order(:name)
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def load_doctor
    @doctor = doctor_from_current_session
    end
    end

    View Slide

  31. class Doctor < ApplicationRecord
    has_many :appointments, order: :appointment_date
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end

    View Slide

  32. class Doctor < ApplicationRecord
    has_many :appointments, order: :appointment_date
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end

    View Slide

  33. class Doctor < ApplicationRecord
    has_many :appointments, order: :appointment_date
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end
    doctor.patients.order(:name)
    Patients Load (1.0ms) SELECT "patients".* FROM "patients"
    INNER JOIN "appointments" ON "patients"."id" = "appointments"."patient_id"
    WHERE “appointments"."doctor_id" = $1
    ORDER BY “appointments"."appointment_date" ASC, "patients"."name" ASC
    irb(main):003:0>

    View Slide

  34. class Doctor < ApplicationRecord
    has_many :appointments
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end
    , order: :appointment_date

    View Slide

  35. class Doctor < ApplicationRecord
    has_many :appointments
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end
    $ rake
    Run options: --seed 45260
    # Running:
    .....F..........FFFF.........F..........FF..............FFFFFFFFF...
    ..............FFFFFFFFFFFFFFFFFF............................FFFF
    Finished in 1.273019s, 24.3516 runs/s, 35.3490 assertions/s.

    View Slide

  36. class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    @patients = @doctor.patients.order(:name)
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def load_doctor
    @doctor = doctor_from_current_session
    end
    end

    View Slide

  37. class PatientsController < ApplicationController
    before_filter :load_doctor
    def index
    @patients =
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def load_patients
    @doctor.patients.sort { |pateint| pateint.name }
    end
    def load_doctor
    @doctor = doctor_from_current_session
    load_patients

    View Slide

  38. Branch history

    View Slide

  39. Pull Request (YOLO)

    View Slide

  40. Build broke...

    View Slide

  41. Build broke...

    View Slide

  42. Just one more commit...

    View Slide

  43. ... and another

    View Slide

  44. Ship it!

    View Slide

  45. Intermission

    View Slide

  46. Intermission

    View Slide

  47. No reorder( ) in Rails 2.3.8
    Intermission

    View Slide

  48. 8 years ago...

    View Slide

  49. Docs-R-Us
    8 years ago...
    Josie

    View Slide

  50. Damn fine coffee!
    8 years ago...

    Josie

    View Slide

  51. Y U NO ALPHABETICAL!?

    View Slide

  52. Branch history

    View Slide

  53. Branch history

    View Slide

  54. Branch history

    View Slide

  55. Git Fu
    1. git rebase --interactive

    View Slide

  56. git rebase --interactive head~3
    Git Fu: git rebase --interactive
    $

    View Slide

  57. git rebase --interactive head~3
    Git Fu: git rebase --interactive
    $

    View Slide

  58. git rebase --interactive head~3
    Git Fu: git rebase --interactive
    $

    View Slide

  59. Git Fu: git rebase --interactive
    git rebase --interactive head~3
    $

    View Slide

  60. Pull Request

    View Slide

  61. Build broke...

    View Slide

  62. Fix the build
    git add test/integration
    $
    $
    [fix-patient-order-bug ee74d2f] Fix patient ordering bug
    Date: Fri Oct 29 09:36:08 2010 +0100
    3 files changed, 44 insertions(+), 3 deletion(-)
    $
    git commit --amend --no-edit

    View Slide

  63. Fix the build
    git push --force-with-lease
    git add test/integration
    $
    $
    [fix-patient-order-bug ee74d2f] Fix patient ordering bug
    Date: Fri Oct 29 09:36:08 2010 +0100
    3 files changed, 44 insertions(+), 3 deletion(-)
    $
    git commit --amend --no-edit

    View Slide

  64. Ship it!

    View Slide

  65. Back to the
    future...

    View Slide

  66. Docs-R-Us
    Seema
    Seema

    View Slide

  67. class PatientsController < ApplicationController
    before_action :load_doctor
    def index
    @patients = sorted_patients
    end
    def show
    @patient = @doctor.patients.find(params[:id])
    end
    private
    def sorted_patients
    @doctor.patients.sort { |patient| patient.name }
    end
    def load_doctor
    @doctor = doctor_from_current_session

    View Slide

  68. 3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 1) # Controller for listing a doctor's pa
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 2) class PatientsController < Application
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 3) before_filter :load_doctor
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 4)
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 5) def index
    6047246d (Josie P 2010-10-29 09:32:25 +0100 6) @patients = sorted_patients
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 7) end
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 8)
    9598514f (Josie P 2010-06-28 17:03:21 +0100 9) def show
    9598514f (Josie P 2010-06-28 17:03:21 +0100 10) @patient = @doctor.patients.find(p
    9598514f (Josie P 2010-06-28 17:03:21 +0100 11) end
    9598514f (Richard E 2010-06-28 17:03:21 +0100 12)
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 13) private
    dbdd0fb9 (Josie P 2010-10-29 09:31:52 +0100 18)
    6047246d (Josie P 2010-10-29 09:32:25 +0100 19) def sorted_patients
    33ec144e (Josie P 2010-10-29 09:31:52 +0100 20) @doctor.patients.sort {|patient| p
    dbdd0f69 (Josie P 2010-10-29 09:31:52 +0100 21) end
    3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 14)
    $ git blame app/controllers/patients_controller.rb
    Git Fu: git blame

    View Slide

  69. $ git log 33ec144e --patch
    commit 33ec144e70b91e6925903553f07df3becc9414
    Author: Josie Pickford
    Date: Friday Oct 29 09:44:49 2010 +0100
    Fix patient ordering bug
    The patients association is returning patients in appointment date
    order, even when called with an explicit `order(:name)` scope. This is
    because the patients association is a has_many :through the appointments
    association, which has a default order by appointment_date. This causes
    any queries on the association to always sort first by appointment date:
    ORDER BY “appointments"."appointment_date" ASC, "patients"."name" ASC)
    Removing the default ordering from the appointments association is going
    to take a bit of unpicking. To get the bug resolved in the meantime we
    can re-sort the patient records after they've been loaded. Separate
    work has been planned to remove the default ordering altogether.
    Git Fu: git blame

    View Slide

  70. class Doctor < ApplicationRecord
    has_many :appointments
    has_many :patients, through: :appointments
    belongs_to :practice
    validates_presence_of :name, :practice
    end

    View Slide

  71. View Slide

  72. • Naming things
    • Automated tests
    • Abstractions
    • Refactoring

    View Slide

  73. Your software
    is more than
    the code

    View Slide

  74. View Slide

  75. Programming as
    Theory Building
    Peter Naur

    View Slide

  76. Revision History as
    Theory Capturing

    View Slide

  77. View Slide

  78. View Slide

  79. View Slide

  80. Git Fu
    1. Configure an environment for good commit
    messages

    View Slide

  81. Configure an environment for good commit messages
    $ git commit -m "Did a thing"

    View Slide

  82. Configure an environment for good commit messages
    $ git config --global core.editor “subl -w”

    View Slide

  83. Configure an environment for good commit messages
    $ git config --global commit.verbose true

    View Slide

  84. Git Fu
    1. Configure an environment for good commit
    messages
    2. Capture the why, not the what

    View Slide

  85. Capture the why, not the what

    View Slide

  86. Git Fu
    1. Configure an environment for good commit
    messages
    2. Capture the why, not the what
    3. Shape each commit

    View Slide

  87. Shape each commit
    • Create small atomic commits
    • Shape as you go, not at the end
    • $ git add --patch / -p

    View Slide

  88. Shape each commit
    dd3b43c Refactor Foo
    44b4bd8 Add Bar to Foo

    View Slide

  89. Git Fu
    1. Configure an environment for good commit
    messages
    2. Capture the why, not the what
    4. Treat (local) commits as mutable
    3. Shape each commit

    View Slide

  90. Treat (local) commits as mutable
    • $ git commit --amend
    • $ git rebase --interactive
    • $ git rebase --abort
    • --fixup / --autosquash

    View Slide

  91. Git Fu
    1. Configure an environment for good commit
    messages
    2. Capture the why, not the what
    5. Build your instincts; search your histories
    4. Treat (local) commits as mutable
    3. Shape each commit

    View Slide

  92. Build your instincts; search your histories
    • $ git blame file.rb
    • $ git log -S "some_code"
    • $ git annotate file.rb

    View Slide

  93. Git Fu
    1. Configure an environment for good commit
    messages
    2. Capture the why, not the what
    5. Treat (local) commits as mutable
    4. Build your instincts; search your histories
    3. Shape each commit

    View Slide

  94. tekin.co.uk

    View Slide

  95. View Slide

  96. View Slide

  97. Thanks for the Git Fu
    @dgheath21
    @angelajtodd
    @grahamashton

    View Slide

  98. Help each
    other Git
    Better

    View Slide

  99. Seema Memoji
    Josie Memoji
    Created by
    Inspiration for the story-based approach
    Talk Feedback and Advice
    Slide Advisor
    Git Fu Indent
    Hospital Icon
    Winding Road Photo
    Sound Effects
    TEKIN SULEYMAN
    TEKIN SULEYMAN
    TEKIN SULEYMAN
    NADIA ODUNAYO
    ANDY CROLL
    ANGELA TODD
    GRAHAM ASHTON
    MURRAY STEELE
    NADIA ODUNAYO
    KATRINA OWEN
    BRUCE LEE, ENTER THE DRAGON (1972)
    FLATICON.COM
    JESSE BOWSER ON UNSPLASH
    LEGEND OF ZELDA, A LINK TO THE PAST
    Cast

    View Slide

  100. Branch in Time
    A story about revision histories
    @tekin

    View Slide