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.

Git-ing out of your git messes - Fluent Conf 2017

1,002 views

Published on

Git, the widely popular version control tool that just about everyone who works on the web seems to use, is powerful, scalable, flexible. . .and difficult to learn. If you’ve used Git for any amount of time, you’ve probably gotten yourself into some confusing, frustrating, or downright terrifying situations. But don’t panic. You are not alone. Katie Sylor-Miller explains how to avoid getting into Git messes in the first place, demonstrating how the fundamental structures in Git actually work under the hood and sharing best practices, workflows, and tools that will keep your commits in order and reduce the panic caused by merge conflicts. Katie then shows you how to leverage Git’s powerful features to save yourself when everything seems to go wrong.

Published in: Engineering
  • Be the first to comment

Git-ing out of your git messes - Fluent Conf 2017

  1. 1. Git-ing out of your Git messes Katie Sylor-Miller @ksylor && @ohshitgit
  2. 2. Etsy is a global marketplace where people around the world connect, both online and offline, to make, sell and buy unique goods.
  3. 3. Don’t git into a mess in the first place
  4. 4. Agenda Fundamental Concepts Workflow in-depth Viewing and changing history Avoiding (and fixing) messes
  5. 5. Commits Branches HEAD History Fundamental concepts
  6. 6. Commits Branches HEAD History Fundamental concepts
  7. 7. What’s in a commit Each commit contains a few pieces of information: • A snapshot of the entire repo • Who made this change • When this change was made • A message describing the commit • A pointer to the previous commit
  8. 8. What’s in a commit SHA-1 Unique 40-char hash Each commit contains a few pieces of information: • A snapshot of the entire repo • Who made this change • When this change was made • A message describing the commit • A pointer to the previous commit
  9. 9. Commit hashes a4df41a8045877d50396d00113598e47f6ad10ef aec561108fd86412c2a9083d7d95ed1668d2f4e4 6dab6a712177cf2dd2cf8b79a2cee24351be60eb 1a3531222242241153ac8a76b752d5f525a99d2c 912bde5d4e5e962269ddff87da83cc5ce55e75d0
  10. 10. Commit hash abbreviations a4df41a aec5611 6dab6a7 1a35312 912bde5
  11. 11. Commits Branches HEAD History Fundamental concepts
  12. 12. Mental model: branches are a linked list a4df41aaec56116dab6a71a35312 912bde5 A B C D E
  13. 13. Mental model: branches are a linked list a4df41aaec56116dab6a71a35312 912bde5 • A snapshot of the entire repo • Who made this change • When this change was made • A message describing the commit • A pointer to the previous commit A B C D E
  14. 14. Mental model: branches are a linked list a4df41aaec56116dab6a71a35312 912bde5 • A snapshot of the entire repo • Who made this change • When this change was made • A message describing the commit • A pointer to the previous commit A B C D E
  15. 15. Branches are a linked list reference A4DF41A6DAB6A7 a4df41aaec56116dab6a71a35312 912bde5 A B C D EA B C D E master
  16. 16. Branches are a linked list reference text file A4DF41A6DAB6A7 a4df41aaec56116dab6a71a35312 912bde5 master .git/refs/heads/master 912bde5d4e5e962269ddff87da83cc5ce55e75d0 A B C D E
  17. 17. ksylormiller:~/ohshitgit (master)$ git branch new-branch 19 Create a new branch
  18. 18. New branches are a new reference A4DF41A6DAB6A7 a4df41aaec56116dab6a71a35312 912bde5 master new-branch A B C D E
  19. 19. New branches are a new text file A4DF41A a4df41aaec56116dab6a71a35312 912bde5 master A B C D E .git/refs/heads/master 912bde5d4e5e962269ddff87da83cc5ce55e75d0 .git/refs/heads/new-branch 912bde5d4e5e962269ddff87da83cc5ce55e75d0 new-branch
  20. 20. Commits Branches HEAD History Fundamental concepts
  21. 21. HEAD points to your currently checked-out branch HEAD a4df41aaec56116dab6a7 912bde5 master new-branch B C D E
  22. 22. HEAD is a reference to a reference HEAD A4DF41A6DAB6A7 a4df41aaec56116dab6a7 912bde5 master new-branch .git/refs/HEAD ref: refs/heads/master B C D E
  23. 23. WTF is the HEAD • The HEAD decides what branch/commit will be the target of your actions • There is only one HEAD per repository • The HEAD is unique to your local install of git • The history of the HEAD is recorded, which gives you a way to undo your work (more on this later)
  24. 24. ksylormiller:~/ohshitgit (master)$ git checkout new-branch 26 Change branches
  25. 25. HEAD points to your currently checked-out branch HEAD a4df41aaec56116dab6a7 912bde5 master new-branch .git/refs/HEAD ref: refs/heads/master B C D E
  26. 26. ksylormiller:~/ohshitgit (master)$ git commit -m “Your message here” 28 Add a new commit to our branch
  27. 27. A new commit becomes the new HEAD 1668d2f HEAD a4df41aaec56116dab6a7 912bde5 master new-branch B C D E F
  28. 28. Commits Branches HEAD History Fundamental concepts
  29. 29. History is a linked list 1668d2fa4df41aaec56116dab6a7 912bde5 master new-branch B C D E F
  30. 30. History is a linked list tree master ca53f4f 1668d2f a4df41a 912bde5 new-branch 3de21fa C D E F G H
  31. 31. ca53f4f 1668d2f fd4ab1a 912bde5 3de21fa new-branch 86bcaed 2d3a4da whee 3037cf2 master 44ff212 4aa3b5f c1d2ea8 40648a8 5ae77a5 omg-stop fd4ab1a and-another History is a linked list tree directed acyclic graph f6e51fd E F G H I J K L M N O P Q R S
  32. 32. Environments A simple workflow A complicated workflow Workflows in depth
  33. 33. Environments A simple workflow A complicated workflow Workflows in depth
  34. 34. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE Central server where shared git repositories are stored -- Remotes typically are “bare” - you can’t directly modify them
  35. 35. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE Your local copy of the remote git repository -- Lives in a .git folder -- Contains the entire history of a remote repo plus local changes
  36. 36. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE Snapshot of changes to the current branch that you want to commit -- Is a copy of all of the files in the repo, not just the changed files
  37. 37. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE Where changes to files are made -- Analogous to the physical directory where files are stored on disk
  38. 38. Environments A simple workflow A complicated workflow Workflows in depth
  39. 39. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER baz.php foo.php bar.php baz.php foo.php bar.php
  40. 40. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER baz.php foo.php bar.php baz.php foo.php bar.php
  41. 41. git status is your BFF by Etsy seller SmittenKittenKendall
  42. 42. ksylormiller:~/ohshitgit (master)$ git status On branch master Your branch is up-to-date with ‘origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: bar.php no changes added to commit (use "git add" and/or "git commit -a”) 44 git status is your BFF
  43. 43. ksylormiller:~/ohshitgit (master)$ git add bar.php 45 git add
  44. 44. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER baz.php foo.php bar.php baz.php foo.php bar.php
  45. 45. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER baz.php foo.php bar.php baz.php foo.php bar.php
  46. 46. ksylormiller:~/ohshitgit (master)$ git commit -m "Meaningful commit message" [master 4875652] Meaningful commit message 1 file changed, 1 insertion(+) 48 git commit
  47. 47. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER baz.php foo.php bar.php
  48. 48. ksylormiller:~/ohshitgit (master)$ git push Counting objects: 4, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 328 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://github.com/ksylor/fluent-example.git 4875652..97e8858 master -> master 50 git push
  49. 49. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER
  50. 50. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER
  51. 51. But… it’s usually not that simple
  52. 52. Environments A simple workflow A complicated workflow Workflows in depth
  53. 53. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER MASTER
  54. 54. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  55. 55. ksylormiller:~/ohshitgit (master)$ git fetch remote: Counting objects: 3, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), done. From https://github.com/ksylor/fluent-example 97e8858..8a97966 master -> origin/master 57 git fetch
  56. 56. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  57. 57. ksylormiller:~/ohshitgit (master)$ git merge origin/master 59 git merge
  58. 58. Merge remote-tracking branch 'origin/master' # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. ~ ~ ~ ~ "~/ohshitgit/.git/MERGE_MSG" 7L, 293C 60 oh god we’re in vim
  59. 59. ksylormiller:~/ohshitgit (master)$ git merge origin/master Updating 97e8858..8a97966 Fast-forward README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md 61 git merge complete
  60. 60. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  61. 61. ksylormiller:~/ohshitgit (master)$ git pull Merge made by the 'recursive' strategy. README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md 63 git pull == git fetch && git merge
  62. 62. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  63. 63. ksylormiller:~/ohshitgit (master)$ git push Counting objects: 8, done. Delta compression using up to 8 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (5/5), 537 bytes | 0 bytes/s, done. Total 5 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/2), completed with 1 local object. To https://github.com/ksylor/fluent-example.git 8a97966..91f6790 master -> master 65 git push
  64. 64. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE ORIGIN/ MASTER MASTERMASTER
  65. 65. Rebase all the things!
  66. 66. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  67. 67. ksylormiller:~/ohshitgit (master)$ git rebase origin/master First, rewinding head to replay your work on top of it... Applying: Meaningful commit message 69 git rebase
  68. 68. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  69. 69. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  70. 70. ksylormiller:~/ohshitgit (master)$ git pull --rebase First, rewinding head to replay your work on top of it... Applying: Meaningful commit message 72 git pull --rebase == git fetch && git rebase
  71. 71. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  72. 72. ksylormiller:~/ohshitgit (master)$ git push Counting objects: 5, done. Delta compression using up to 8 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 331 bytes | 0 bytes/s, done. Total 3 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), completed with 1 local object. To https://github.com/ksylor/fluent-example.git f6e51fd..3c2335c master -> master 74 git push
  73. 73. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  74. 74. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER MASTER
  75. 75. Viewing history Changing history Viewing and changing history
  76. 76. Viewing history Changing history Viewing and changing history
  77. 77. View the history of a branch 1668d2f HEAD a4df41aaec56116dab6a7 912bde5 master B C D E F
  78. 78. ksylormiller:~/ohshitgit (master)$ git log commit 3c2335c50a1ad48a283a475e3d3f9ac445a20ff5 Author: Katie Sylor-Miller <katie@ohshitgit.com> Date: Thu Jun 8 23:42:05 2017 -0400 Another awesome commit A detailed message about this commit goes here commit f6e51fdd6650c7bbc39895c0392ec6a9fb5a9c15 Author: Someone else <someone@ohshitgit.com> Date: Thu Jun 8 23:39:36 2017 -0400 Oh hai this is a change commit 4f9a80ff7732f252ffbe7841e96748707da1a78d 80 git log
  79. 79. by Etsy seller Birdwoodshack git reflog is your magic time machine
  80. 80. ksylormiller:~/ohshitgit (master)$ git reflog 3c2335c HEAD@{0}: rebase finished: returning to refs/heads/master 3c2335c HEAD@{1}: pull --rebase: lolz f6e51fd HEAD@{2}: pull --rebase: checkout f6e51fdd6650c7bbc39895c0392ec6a9fb5a9c15 f4f4d99 HEAD@{3}: reset: moving to HEAD@{4} f6e51fd HEAD@{4}: reset: moving to HEAD~ 1ecad3a HEAD@{5}: rebase finished: returning to refs/heads/master 1ecad3a HEAD@{6}: rebase: lolz f6e51fd HEAD@{7}: rebase: checkout origin/master f4f4d99 HEAD@{8}: commit: lolz 4f9a80f HEAD@{9}: commit: Another awesome commit 4875652 HEAD@{10}: commit: Meaningful commit message 82 git reflog
  81. 81. HEAD notation • HEAD@{index} : go to a specific point • HEAD~ == HEAD@{currentindex+1} : back one action • HEAD~x == HEAD@{currentindex+x} : back x actions • Or, you can always reference by hash
  82. 82. ksylormiller:~/ohshitgit (master)$ git show HEAD@{8} commit f4f4d996d44bbf824cdd22ace9e6d154d27c9a5d Author: Katie Sylor-Miller <katie@ohshitgit.com> Date: Thu Jun 8 23:42:05 2017 -0400 lolz diff --git a/bar.php b/bar.php index f81fce0..bdd3cb3 100644 --- a/bar.php +++ b/bar.php @@ -1 +1,4 @@ this is a file -with nothing +with some lolz 84 git show
  83. 83. ksylormiller:~/ohshitgit (master)$ git checkout HEAD@{8} Note: checking out 'HEAD@{8}'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at a4df41a... Merge remote-tracking branch 'origin/master' ksylormiller:~/ohshitgit (master) ((detached from a4df41a))$ 85 git checkout
  84. 84. A detached HEAD is when your HEAD points directly to a commit or a tracking branch (not an editable branch) WTF is a detached HEAD?
  85. 85. post-checkout detached HEAD 1668d2f HEAD a4df41aaec56116dab6a7 912bde5 master B C D E F
  86. 86. Viewing history Changing history Viewing and changing history
  87. 87. Changing history of a branch 1668d2f HEAD a4df41aaec56116dab6a7 master B C D E F 912bde5
  88. 88. git reset brings you back to a previous state in history, undoing everything that changed between now and then Hit the reset button
  89. 89. ksylormiller:~/ohshitgit (master)$ git reflog 1668d2f HEAD@{0}: rebase finished: returning to refs/heads/master 3c2335c HEAD@{1}: pull --rebase: lolz 912bde5 HEAD@{2}: pull --rebase: checkout f6e51fdd6650c7bbc39895c0392ec6a9fb5a9c15 f4f4d99 HEAD@{3}: commit: lolz 91 git reflog
  90. 90. ksylormiller:~/ohshitgit (master)$ git reset HEAD@{3} Unstaged changes after reset: M foo.php 92 git reset
  91. 91. Three basic types of resetting Discards the changes from the affected commits Leaves the changes from the affected commits in the workspace (default) --hard--mixed--soft Leaves the changes from the affected commits in staging
  92. 92. Post-reset 1668d2f HEAD a4df41aaec56116dab6a7 master Changes move to the index or workspace or discarded 912bde5 B C D E F
  93. 93. Disclaimer: never change public history
  94. 94. git revert creates a new commit that undoes the changes in the specified commit(s) Undo a public commit
  95. 95. ksylormiller:~/ohshitgit (master)$ git revert f4f4d99 97 git revert
  96. 96. Revert "lolz" This reverts commit f4f4d996d44bbf824cdd22ace9e6d154d27c9a5d. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Your branch is ahead of 'origin/master' by 3 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: bar.php # ~ "~/ohshitgit/.git/COMMIT_EDITMSG" 14L, 450C 98 ugh, vim again
  97. 97. ksylormiller:~/ohshitgit (master)$ git revert f4f4d996d44bbf824cdd22ace9e6d154d27c9a5d [master b483271] Revert "lolz" 1 file changed, 3 deletions(-) 99 git revert complete
  98. 98. Post-revert 1668d2f HEAD a4df41aaec5611 b75fb8b912bde5 master reverts changes from C D E F G
  99. 99. Always be committing Always be branching Avoiding & getting out of messes
  100. 100. Always be committing Always be branching Avoiding & getting out of messes
  101. 101. Lots of commits are better • Commits are cheap and easy • Save your progress over time • Easier to backtrack if you screw up • Less chance of committing the wrong thing when you are reviewing small changes
  102. 102. Problem: Committing the wrong thing
  103. 103. • Set up your command line to show you what branch you are on • Use .gitignore to your advantage • Remember git status is your BFF • Understand how staging works (subsequent changes to a file are not reflected) Avoid the problem: Committing the wrong thing
  104. 104. ksylormiller:~/ohshitgit (master)$ git commit --amend # insert vim here 106 Fix the problem: Entering the wrong commit message
  105. 105. ksylormiller:~/ohshitgit (master)$ git commit --amend [master f0c2e62] My correct commit message 1 file changed, 3 deletions(-) 107 Fix the problem: Entering the wrong commit message
  106. 106. ksylormiller:~/ohshitgit (master)$ git add file/i/forgot/to/commit.ext ksylormiller:~/ohshitgit (master)$ git commit --amend —no-edit [master 014035a] My correct commit message 1 file changed, 1 insertion(+), 3 deletions(-) 108 Fix the problem: Forgetting to commit a file
  107. 107. Always be committing Always be branching Avoiding & getting out of messes
  108. 108. • Safety net: you aren’t changing master directly until your feature is ready for prime time • Allows you to switch between tasks/manage unrelated changes • Share larger features or long-term work with your team and preserve its history • Caution: Don’t use long-lived feature branches Why a feature branch workflow is better
  109. 109. Problem: Staying up to date
  110. 110. MERGE Adds a new commit to your feature branch. You are resolving potential conflicts created by other people’s code. Replays your commits on top of the latest of master. You are resolving potential conflicts created by your own code. REBASE Merge vs. rebase
  111. 111. Problem: Rebasing kinda sucks
  112. 112. ksylormiller:~/ohshitgit (feature-branch)$ git rebase -i HEAD~2 114 Avoid the problem: Combine commits before rebasing
  113. 113. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER FEATURE- BRANCH MASTER
  114. 114. pick 2f5bae4 example feature branch pick 0ee2a20 Another commit # Rebase aaff258..0ee2a20 onto aaff258 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell ~ "~/ohshitgit/.git/rebase-merge/git-rebase-todo" 20L, 670C 116 Interactive rebase
  115. 115. pick 2f5bae4 example feature branch fixup 0ee2a20 Another commit # Rebase aaff258..0ee2a20 onto aaff258 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell ~ "~/ohshitgit/.git/rebase-merge/git-rebase-todo" 20L, 670C 117 Interactive rebase
  116. 116. ksylormiller:~/ohshitgit (feature-branch)$ git rebase -i HEAD~2 [detached HEAD a682e3a] example feature branch 3 files changed, 5 insertions(+) Successfully rebased and updated refs/heads/feature-branch. 118 Avoid rebasing problems: combine commits
  117. 117. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER ORIGIN/ MASTER FEATURE- BRANCH MASTER
  118. 118. Problem: Merging back into master
  119. 119. REMOTE/ORIGIN Your machineGithub LOCAL STAGING/INDEX WORKSPACE MASTER FEATURE- BRANCH
  120. 120. Problem: Merge conflicts
  121. 121. • Update your local master and origin/master all.the.time. • Rebase your feature branches to stay up to date • Periodically squash feature branch commits to reduce the number of conflicts to resolve (esp. when rebasing) • Communication with teammates • If things don’t seem right, abort! Avoid the problem: Merge conflicts
  122. 122. ksylormiller:~/ohshitgit (master)$ git diff --check foo.php:1: leftover conflict marker foo.php:4: leftover conflict marker foo.php:5: trailing whitespace. +fdfakadsfldjfasd^M foo.php:6: leftover conflict marker 126 check your diffs before committing!
  123. 123. That’s it! Easy, right?
  124. 124. • Understand the fundamentals (commits, branches, HEAD, history, workflows) • Know how to view & fix history (reflog is git’s magic time machine) • Always be committing • Always be branching (but stay up to date) • DON’T PANIC, everything is fixable Avoid git messes in the first place
  125. 125. If all else fails ohshitgit.com
  126. 126. Thank you! @ksylor @ohshitgit

×