Design Systems are most successful when they have a solid process in place to manage, maintain, and share component code across multiple teams and codebases. The best way to achieve this is to manage code using a version control system like Git. Git is the defacto industry standard tool for storing and editing code for a reason - it's powerful, scalable, flexible... but can be confusing or intimidating, whether you're a newbie or you use it every day!
In this workshop, Katie Sylor-Miller, the creator of OhShitGit.com, and co-author of The Design Systems Handbook, will teach you all you need to know to use Git as a tool for managing your Design System code.
We'll walk through everything you need to know to create, contribute to, maintain, and share your design system code as a standalone repo in Git. We'll go over how the fundamental structures in Git and how it all works under the hood. We'll create our own repos and get comfortable running common git commands in the terminal. We'll learn about best practices, workflows, and tools that will keep your commits in order and reduce the panic caused by merge conflicts. And, we'll cover some cool features in the Github UI to help you document, manage, and share your Design System code.
18. Distributed Version Control
• A “cloned” copy of the entire repository - including all files,
metadata, and it’s full history - is mirrored on each user’s
local host machine.
• Usually (but not always!) there is a central/canonical copy of
the repository stored in a remote git server called origin.
• You can configure multiple remote repositories, even
another repo on your machine can be a remote!
27. Benefits of Git
• Historical context - view and compare different versions of
files to understand what changed and why.
• Safety net - if you make a mistake, you can easily revert
back in time to a previous version of a file.
• Collaboration - multiple people can work on the same files
at the same time, then share their changes with each other.
• Conflict resolution - Git can resolve conflicts that arise
when multiple people make changes to the same file.
28. Benefits of Git for Design Systems
• Sandboxing - you can work on changes locally, without
affecting anyone else, until they are ready to be shared.
• Versioned releases - you can control when you are ready to
share code with other teams.
• Quality control - pull requests allow core team members to
review file changes before they end up in a release.
• Documentation - the Github interface has simple
documentation capabilities built-in.
30. Git
A tool for distributed
version control
(the stuff you do in the
command line)
A company that hosts
Git repos (with some
extra features)
(the stuff you do in the
github.com website)
Github
31. Cloning and Creating Repos
https://github.com/ksylor/clarity-workshop-exercises/
tree/master/exercise-1
Exercise 1
35. 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
36. 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
42. 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
43. 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
44. Branches are a linked list reference
A4DF41A6DAB6A7
a4df41aaec56116dab6a71a35312 912bde5
A B C D EA B C D E
master
45. Branches are a linked list reference text file
A4DF41A6DAB6A7
a4df41aaec56116dab6a71a35312 912bde5
master
.git/refs/heads/master
912bde5d4e5e962269ddff87da83cc5ce55e75d0
A B C D E
47. New branches are a new reference
A4DF41A6DAB6A7
a4df41aaec56116dab6a71a35312 912bde5
master
new-branch
A B C D E
48. 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
50. HEAD points to your currently checked-out branch
HEAD
a4df41aaec56116dab6a7 912bde5
master
new-branch
B C D E
51. 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
52. 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)
54. HEAD points to your currently checked-out branch
HEAD
a4df41aaec56116dab6a7 912bde5
master
new-branch
.git/refs/HEAD
ref: refs/heads/new-branch
B C D E
61. Fundamental concepts: recap
• Commits are a unique snapshot of a repository at a single
point in time
• History is a linked list tree directed acyclic graph
• Branches are a reference to a single commit in history
• HEAD is a symbolic reference to your current working branch
62. Commits, Branches,
Refs and HEAD
https://github.com/ksylor/clarity-workshop-exercises/tree/
master/exercise-2
Exercise 2
68. REMOTE/ORIGIN
Your machineGithub
LOCAL STAGING/INDEX WORKSPACE
Your local copy of the
remote git repository
--
Lives in a .git folder
inside your local copy
folder
--
Contains the entire
history of a remote repo
plus local changes
77. 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”)
77
git status is your BFF
78. git status and
git diff
are your BFFs
by Etsy seller SmittenKittenKendall
79. ksylormiller:~/ohshitgit (master)$ git diff
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 in it
+with some stuff in it
79
git diff is your other BFF
80. REMOTE/ORIGIN
Your machineGithub
LOCAL STAGING/INDEX WORKSPACE
git diff
compares changes
in workspace
to changes
(if any) in index
git diff --staged
compares changes
in index to HEAD
(e.g. current state
of your checked-out
branch)
git diff HEAD
compares changes
in both index and
workspace to HEAD
83. ksylormiller:~/ohshitgit (master)$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: bar.php
83
git status (again)
85. ksylormiller:~/ohshitgit (master)$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: bar.php
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
85
git status (I told you it was our BFF)
98. 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
98
oh god we’re in vim
107. ksylormiller:~/ohshitgit (master)$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: Meaningful commit message
107
git rebase
110. ksylormiller:~/ohshitgit (master)$ git pull --rebase
First, rewinding head to replay your work on top of it...
Applying: Meaningful commit message
110
git pull --rebase == git fetch && git rebase
116. Workflows in depth: recap
• We interact with git repos via remote (bare) servers, and on
your machine w/ it’s local copy, workspace, and staging
area
• git add takes a snapshot of a changed file in it’s current
state & adds it to staging
• git status and git diff your BFFs
• We interact with the remote via tracking branches, another
kind of reference
117. Workflows in depth: recap
• git pull = git fetch && git merge
creates a new merge commit (gross! vim! no!)
• git pull --rebase = git fetch && git rebase
replays your work at the tip of master (beautiful! yes!)
126. ksylormiller:~/ohshitgit (feature-branch)$ git status
On branch feature-branch
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”)
126
git status
127. ksylormiller:~/ohshitgit (feature-branch)$ git diff
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 in it
+with some stuff in it
127
git diff
134. Pull Requests (PRs)
• An additional feature on top of core Git functionality.
• PRs do a diff comparison between two branches - usually
comparing a feature branch to the current state of master.
• Allows teammates to review code, ask questions, find
possible bugs before code hits production.
• Provides a nice visual way to confirm that the code in your
branch contains only the changes that you want!
163. ksylormiller:~/ohshitgit (feature-branch)$ git checkout master
On branch master
Your branch is behind 'origin/master' by 2 commits, and can be fast-
forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
ksylormiller:~/ohshitgit (master)$
163
checkout master
164. ksylormiller:~/ohshitgit (master)$ git pull --rebase
Updating 74877c3..2ea524f
Fast-forward
fun.txt | 2 ++
1 file changed, 2 insertions(+)
Current branch master is up to date.
ksylormiller:~/ohshitgit (master)$
164
update master
165. ksylormiller:~/ohshitgit (master)$ git merge --squash feature-branch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
165
Squash merging
177. View the history of a branch
1668d2f
HEAD
a4df41aaec56116dab6a7 912bde5
master
B C D E F
178. 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
178
git log
179. ksylormiller:~/ohshitgit (master)$ git log --oneline
3c2335c Another awesome commit
f6e51fd Oh hai this is a change
91f6790 Meaningful commit message
4f9a80f Fake commit messages are hard
8a97966 Is anyone actually reading this?
97e8858 Lolz
4875652 Hello world
179
Short history
180. by Etsy seller Birdwoodshack
git reflog
is your magic
time machine
181. 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
181
git reflog
182. 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
183. 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
183
git show
184. 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))$
184
git checkout
185. 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?
187. • Checking out an existing branch - throws away any work you
might have done
• Create a new branch from this state - allows you to save any
work, or create a branch from any point in time
Re-attaching the HEAD
188. Checkout all the things
Checkout can be used to move the HEAD OR checkout can also
change the state of a file in the workspace (w/o moving HEAD)
• Discard workspace changes to a file or directory
git checkout -- path/to/file/or/dir/
• Reset file or dir to state in history (then commit to save!)
git checkout <commit hash> —-path/to/file/or/dir/
• Get state of a file or dir from another branch (then commit)
git checkout other-branch --path/to/file/or/dir/
194. 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
199. 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
199
ugh, vim again
202. Viewing and changing history: recap
• git log shows the history of your branch
• git reflog shows the history of the HEAD aka the magic time
machine
• git checkout lets you view a previous state of the repo in a
read-only “detached HEAD” state
• git reset lets you go back in time and change things
• git revert creates a new commit to undo changes
203. Viewing and Changing History
https://github.com/ksylor/clarity-workshop-exercises/tree/
master/exercise-5
Exercise 5
207. Why version your design system?
• You won’t get it perfect the first time, so you need to plan
for how to handle changes to your code.
• With versioning, you make controlled releases of changes to
your code, and consuming teams can chose which version
they use, and when and how to upgrade (or not!).
• Versions allow you to release breaking changes, e.g. a
change that will break existing uses of a pattern, without
disrupting existing users.
208. Semver (Semantic Versioning)
0.1.0
Major Release
Changes are not
backwards-
compatible with
prior versions
More info at semver.org
Minor Release
New functionality
is backwards-
compatible with
prior versions
Patch Release
Only contains
bug fixes, which
are backwards-
compatible
211. ksylormiller:~/ohshitgit (master)$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
211
npm init
212. package name: (clarity-workshop-example)
version: (1.0.0) 0.1.0
description: An example npm package for clarity workshop
entry point: (index.js)
test command:
git repository: (https://github.com/ksylor/clarity-workshop-example.git)
keywords:
author: Katie Sylor-Miller
license: (ISC)
About to write to /Users/ksylormiller/clarity-workshop-example/package.json:
212
npm init (cont)
213. {
"name": "clarity-workshop-example",
"version": "0.1.0",
"description": "An example npm package for clarity workshop",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ksylor/clarity-workshop-example.git"
},
"author": "Katie Sylor-Miller",
"license": "ISC",
"bugs": {
"url": "https://github.com/ksylor/clarity-workshop-example/issues"
},
"homepage": "https://github.com/ksylor/clarity-workshop-example#readme"
}
Is this OK? (yes) yes
213
npm init (cont)
214. ksylormiller:~/ohshitgit (master)$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
package.json
nothing added to commit but untracked files present (use "git add" to track)
214
package.json
221. ksylormiller:~/someotherproject (master)$ npm install --save-dev https://
github.com/ksylor/clarity-workshop-example/archive/v0.1.1.tar.gz
npm notice created a lockfile as package-lock.json. You should commit this
file.
+ clarity-workshop-example@0.1.0
added 1 package from 1 contributor and audited 1 package in 1.325s
found 0 vulnerabilities
221
add your package as a dependency to another project
235. • Set up your command line to show you what branch you are on
• Remember git status and git diff your BFFs
• Understand how staging works (subsequent changes to a file
are not reflected
• Use a feature branch so you don’t accidentally commit to
master!
Avoid the problem: Committing the wrong thing
238. 238
vim again :(
My wrong commit message
# 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
239. 239
vim again :(
My right commit message
# 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
240. ksylormiller:~/ohshitgit (master)$ git commit --amend
[master f0c2e62] My correct commit message
1 file changed, 3 deletions(-)
240
Fix the problem: Entering the wrong commit message
241. ksylormiller:~/ohshitgit (master)$ git add file/i/forgot/to/commit.ext
ksylormiller:~/ohshitgit (master)$ git commit --amend —no-edit
[master 014035a] My commit message
1 file changed, 1 insertion(+), 3 deletions(-)
241
Fix the problem: Forgetting to commit a file, or just one small change
252. ksylormiller:~/ohshitgit (master)$ git stash list
stash@{0}: WIP on master: 3c2335c lolz
stash@{1}: WIP on feature-branch: a682e3a my feature rocks
stash@{2}: WIP on master: f6e51fd oh hai
stash@{3}: WIP on master: 6d4cf2d something else
252
git stash list
253. ksylormiller:~/ohshitgit (master)$ git stash save “started on ticket OSG-42”
Saved working directory and index state WIP on master: 3c2335c lolz
253
git stash save a better message
254. ksylormiller:~/ohshitgit (master)$ git stash list
stash@{0}: WIP on master: started on ticket OSG-42
stash@{1}: WIP on feature-branch: a682e3a my feature rocks
stash@{2}: WIP on master: f6e51fd oh hai
stash@{3}: WIP on master: 6d4cf2d something else
254
git stash list again
255. ksylormiller:~/ohshitgit (master)$ git stash show -p
diff --git a/bar.php b/bar.php
index ebc0bc8..a44188c 100644
--- a/bar.php
+++ b/bar.php
@@ -1,4 +1,8 @@
+aaaaaaa
+fdfjdklfjdsalf;j
fdafsdfas
fdafdsfdas
fdfadasfdas
this is a file
255
viewing a stash entry
256. ksylormiller:~/ohshitgit (master)$ git stash pop
On branch feature-branch
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
ksylormiller:~/ohshitgit (master)$ git stash apply
256
pop changes back off the stack
258. Stash tips and tricks
• git stash --keep-index - leaves the index intact after
stashing changes.
• git stash --patch - opens interactive mode for deciding
what chunks of what files to stash.
• git stash —include-untracked - save untracked files
(w/o this flag untracked files are only included if they are in
the index)
259. ksylormiller:~/ohshitgit (master)$ git reset HEAD~ —soft
ksylormiller:~/ohshitgit (master)$ git stash
Saved working directory and index state WIP on master: 3c2335c lolz
ksylormiller:~/ohshitgit (master)$ git checkout feature-branch
Switched to branch ‘feature-branch’
259
Option 1: Fix committing to the wrong branch
260. ksylormiller:~/ohshitgit (feature-branch)$ git stash pop
On branch feature-branch
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: baz.php
modified: foo.php
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (3c0529b7e598984b78647f391eab1ca6fd7897a0)
ksylormiller:~/ohshitgit (feature-branch)$ git commit -am “on the right branch
now”
260
Option 1: Fix committing to the wrong branch
265. ksylormiller:~/ohshitgit (feature-branch)$ git checkout master
ksylormiller:~/ohshitgit (master)$ git reset --hard HEAD~
HEAD is now at fcebc22 my prior commit message
ksylormiller:~/ohshitgit (master)$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
265
Option 2: Fix committing to the wrong branch
271. 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
271
Interactive rebase
272. 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
272
Interactive rebase
273. 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.
273
Avoid rebasing problems: combine commits
275. ksylormiller:~/ohshitgit (master)$ git merge-base master feature-branch
3c2335c50a1ad48a283a475e3d3f9ac445a20ff5
ksylormiller:~/ohshitgit (feature-branch)$ git rebase -i 3c2335c
275
If you don’t know how many commits to go back
278. ksylormiller:~/ohshitgit (master)$ git merge --squash feature-branch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
278
Squash merging
283. • 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
286. Merge master into your
feature branch
Rebase master against
your feature branch
Merge your feature
branch into master
Rebase your feature
branch against master
Merge and rebase in the right direction
DON’T DO
287. ksylormiller:~/ohshitgit (master)$ git merge feature-branch
Auto-merging conflict_file.txt
CONFLICT (content): Merge conflict in conflict_file.txt
Automatic merge failed; fix conflicts and then commit the result.
ksylormiller:~/ohshitgit (master)$ cat conflict_file.txt
<<<<<<< HEAD
this code
is from master
=======
this code
is from feature-branch
>>>>>>>> d34367
287
Conflict markers
290. Avoiding & getting out of messes: Recap
• Always be committing - commits are cheap and easy to use!
• git commit --amend for when you mess up a commit
• Always be branching - feature branch workflow FTW
• Stay up to date
• Squash branches into a single commit before rebasing
• Squash merge back into master
• Use a visual merge tool whenever you can