Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Branch in Time (a story about revision histories)

178 views

Published on

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

This is a story about writing maintainable software. But rather than the code itself, we’ll see how a well-crafted revision history is as important to maintainability as choosing the right abstraction. We'll explore the differences between a useful history and an unhelpful one. And you'll learn about the practices, tools and techniques that help make the difference.

Published in: Software
  • Be the first to comment

Branch in Time (a story about revision histories)

  1. 1. Branch in Time A story about revision histories @tekin
  2. 2. Docs-R-UsSeema
  3. 3. Seema Docs-R-Us
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 9. Git Fu 1. git blame
  10. 10. $ git blame app/controllers/patients_controller.rb Git Fu: git blame
  11. 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
  12. 12. --patch Git Fu: git blame $ git log dbdd0fb9
  13. 13. $ git log dbdd0fb9 --patch commit dbdd0fb9e870b91e6925903553f07df3becc9414 Author: Josie Pickford<josie@docs-r-us.com> 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
  14. 14. Git Fu 1. git blame 2. git log -S (AKA The Pickaxe)
  15. 15. Git Fu: git log -S (AKA The Pickaxe) $ git log -S "sorted_patients" --patch --reverse
  16. 16. Git Fu: git log -S (AKA The Pickaxe) $ git log -S "sorted_patients" --patch --reverse commit 23b6e0c6a9a7a392c312d4f0c51153e0769ebffc Author: Josie Pickford<josie@docs-r-us.com> 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
  17. 17. Git Fu 1. git blame 2. git log -S (AKA The Pickaxe) 3. Pickaxe Round 2
  18. 18. Git Fu: Pickaxe Round 2 $ git log -S "load_patients" --patch --reverse commit 66f95816017b1c6582034d074333fa18884ad3c3 Author: Josie Pickford<josie@docs-r-us.com> 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
  19. 19. Git Fu 1. git blame 2. git log -S (AKA The Pickaxe) 3. Pickaxe Round 2 4. Find the Pull Request
  20. 20. Git Fu: Find the Pull Request
  21. 21. Git Fu: Find the Pull Request
  22. 22. Git Fu: Find the Pull Request
  23. 23. Git Fu: Find the Pull Request
  24. 24. 8 years ago...
  25. 25. Docs-R-UsJosie 8 years ago...
  26. 26. Doh! ☕💦 8 years ago... Josie
  27. 27. Y U NO ALPHABETICAL!?
  28. 28. 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
  29. 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
  30. 30. class Doctor < ApplicationRecord has_many :appointments, order: :appointment_date has_many :patients, through: :appointments belongs_to :practice validates_presence_of :name, :practice end
  31. 31. class Doctor < ApplicationRecord has_many :appointments, order: :appointment_date has_many :patients, through: :appointments belongs_to :practice validates_presence_of :name, :practice end
  32. 32. 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>
  33. 33. class Doctor < ApplicationRecord has_many :appointments has_many :patients, through: :appointments belongs_to :practice validates_presence_of :name, :practice end , order: :appointment_date
  34. 34. 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.
  35. 35. 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
  36. 36. 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
  37. 37. Branch history
  38. 38. Pull Request (YOLO)
  39. 39. Build broke...
  40. 40. Build broke...
  41. 41. Just one more commit...
  42. 42. ... and another
  43. 43. Ship it!
  44. 44. Intermission
  45. 45. Intermission
  46. 46. No reorder( ) in Rails 2.3.8 Intermission
  47. 47. 8 years ago...
  48. 48. Docs-R-Us 8 years ago... Josie
  49. 49. Damn fine coffee! 8 years ago... ☕Josie
  50. 50. Y U NO ALPHABETICAL!?
  51. 51. Branch history
  52. 52. Branch history
  53. 53. Branch history
  54. 54. Git Fu 1. git rebase --interactive
  55. 55. git rebase --interactive head~3 Git Fu: git rebase --interactive $
  56. 56. git rebase --interactive head~3 Git Fu: git rebase --interactive $
  57. 57. git rebase --interactive head~3 Git Fu: git rebase --interactive $
  58. 58. Git Fu: git rebase --interactive git rebase --interactive head~3$
  59. 59. Pull Request
  60. 60. Build broke...
  61. 61. 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
  62. 62. 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
  63. 63. Ship it!
  64. 64. Back to the future...
  65. 65. Docs-R-UsSeemaSeema
  66. 66. 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
  67. 67. 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
  68. 68. $ git log 33ec144e --patch commit 33ec144e70b91e6925903553f07df3becc9414 Author: Josie Pickford<josie@docs-r-us.com> 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
  69. 69. class Doctor < ApplicationRecord has_many :appointments has_many :patients, through: :appointments belongs_to :practice validates_presence_of :name, :practice end
  70. 70. • Naming things • Automated tests • Abstractions • Refactoring
  71. 71. Your software is more than the code
  72. 72. Programming as Theory Building Peter Naur
  73. 73. Revision History as Theory Capturing
  74. 74. Git Fu 1. Configure an environment for good commit messages
  75. 75. Configure an environment for good commit messages $ git commit -m "Did a thing"
  76. 76. Configure an environment for good commit messages $ git config --global core.editor “subl -w”
  77. 77. Configure an environment for good commit messages $ git config --global commit.verbose true
  78. 78. Git Fu 1. Configure an environment for good commit messages 2. Capture the why, not the what
  79. 79. Capture the why, not the what
  80. 80. Git Fu 1. Configure an environment for good commit messages 2. Capture the why, not the what 3. Shape each commit
  81. 81. Shape each commit • Create small atomic commits • Shape as you go, not at the end • $ git add --patch / -p
  82. 82. Shape each commit dd3b43c Refactor Foo 44b4bd8 Add Bar to Foo
  83. 83. 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
  84. 84. Treat (local) commits as mutable • $ git commit --amend • $ git rebase --interactive • $ git rebase --abort • --fixup / --autosquash
  85. 85. 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
  86. 86. Build your instincts; search your histories • $ git blame file.rb • $ git log -S "some_code" • $ git annotate file.rb
  87. 87. 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
  88. 88. tekin.co.uk
  89. 89. Thanks for the Git Fu @dgheath21@angelajtodd@grahamashton
  90. 90. Help each other Git Better
  91. 91. 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
  92. 92. Branch in Time A story about revision histories @tekin

×