GIT ANTIPATTERNS
How To Mess Up With Git and Love It Again
LEMi ORHAN ERGiNAgile Software Craftsman, iyzico
/lemiorhan lemiorhanergin.com @lemiorhan
28 common git anti-patterns
DISCLOSUREThere is no formula for using git efficiently.
Opinions are my own. It means the opposites might work perfectly for your conditions.
GIT
git is powerfulbut you have to know using it properly
Are you using git
if all you do is commit-push-pulluse dropbox instead
ANTIPATTERN DANGER
as if it is dropbox ?
1DROPBOX-ISH GIT ANTI-PATTERN
learn how git worksno worries, I will cover how git behaves
the way it keeps FILES & FOLDERS
working copy staging area
objects database repository
the way it keeps REFERENCESdirected acyclic graph keeping snapshots traversing graph branches, tags, heads
git has 2 mechanisms
Source CodeWorking Copy
you want to version changes
Source CodeWorking Copy
$ git init
Object Database.git Folder / Object Database
CacheStaging Area / The Index
initializing repo
Source CodeWorking Copy
$ git init --bare
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
initializing bare repo
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git add . preparing commits
folder
folder
folder
file
file
file
$ git add . preparing commits
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git add . preparing commits
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git commit -m “initial commit” commi!ing
$ git commit -m “initial commit” commi!ing
folder
folder
folder
file
file
file
commit
branch
HEAD
For more details, refer to book Git Internals by Scott Chacon
folder
folder
folder
file
file
file
commit
$ git commit -m “second commit” commi!ing
folder
commit
branch
HEAD
folder
file
folder
For more details, refer to book Git Internals by Scott Chacon
folder
folder
folder
file
file
file
commit
$ git commit -m “third commit” commi!ing
folder
commit
folder
file
folder
folder
commit
branch
HEAD
file
For more details, refer to book Git Internals by Scott Chacon
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git commit -m “initial commit” commi!ing
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git remote add origin http://upstream.repo$ git push -u origin master pushing to remote
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
new changes from others are pushed
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git fetch fetching changes
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git merge FETCHED_HEAD updating working copy
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git pullgit fetch + git merge
ge!ing changes to source code
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
want to update last commit
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git reset --soft $ git commit --amend/ so" reseting
cannot be reached
Only the cache for the commit you reseted
is removed from staging area
for your current branch
folder
folder
folder
file
file
file
commit
folder
commit
folder
file
folder
folder
commit
branch
HEAD
file
For more details, refer to book Git Internals by Scott Chacon
$ git reset --soft $ git commit --amend/ so" reseting
folder
folder
folder
file
file
file
commit
folder
commit
folder
file
folder
folder
commit
branch
HEAD
file
For more details, refer to book Git Internals by Scott Chacon
$ git reset --soft $ git commit --amend/ so" reseting
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
want to squash or change last commits
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git reset --mixed mixed reseting
cannot be reached
entries for commits, files
and folders are removed from staging area
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
want to get rid of last commits
Object Database.git Folder / Object Database
CacheStaging Area / The Index
RemoteUpstream Repo / Remote Repo
Server
Source CodeWorking Copy
$ git reset --hard hard reseting
cannot be reached
removed from staging area
removed from working copy
are you brave enough tojump to any commit ?
jump to a branch
create a branch from a commit
create a branch from a tag
ANTIPATTERN DANGER
$ git checkout feature/PA-121 $ git checkout -b fix/missing-sign-parameter 2449be8 $ git checkout -b hotfix/v1.1 tags/v1
2BROKEN TIME MACHINE ANTI-PATTERN
are you sure?
are you brave enough tojump to any commit ?
do you haveloooooong living
topic branches ?
ANTIPATTERN DANGER
3LONG LIVING BRANCHES ANTI-PATTERN
do you haveloooooong living
topic branches ?
welcome tomerge hell
before mergingdo you validate commits
back to source ?
ANTIPATTERN DANGER
code review, continuous integration, automated testing…
4TOO LATE TO VALIDATE ANTI-PATTERN
before mergingdo you validate commits
back to source ? are you sure?
merge and unmergedo you o!en want to
just before releases ?
ANTIPATTERN DANGER
5CHERRY-PICK OBSSESSION ANTI-PATTERN
merge and unmergedo you o!en want to
just before releases ?
master
HEAD
TAG/v13
version 14
$ git cherry-pick Every-Single-Commit-We-Want-To-Deploy
the commit graph ?do you fully understand
ANTIPATTERN DANGER
6DEATH ON COMMIT GRAPH ANTI-PATTERN
the commit graph ?do you fully understand
topic and shared branches, tracking branches, tags, HEADs, merge commits, reverted commits…
Cure?
Commit Early, Commit O"en Perfect Later, Publish Once
STEP 0
split your big feature into mini shippable tasks
master
HEAD
TOPIC
ORIGIN/master
refactorings tasks, like rest endpoints testable, deployable
each task will have a branch, not a feature
STEP 1
commit early commit o!en no need to compile no need for CI it’s only for versioning
do not push
master
HEAD
TOPIC
ORIGIN/master
always pull with rebase
$ git pull --rebase origin master
to get forced pushes securely to rebase your commits
master
HEAD
TOPIC
STEP 2
ORIGIN/master
always pull with rebase
$ git pull --rebase origin master
to get forced pushes securely to rebase your commits
master
HEAD
TOPIC
STEP 2
ORIGIN/master
always pull with rebase
$ git pull --rebase origin master
to get forced pushes securely to rebase your commits
master
HEAD
TOPIC
STEP 2
ORIGIN/master
if you branch is pushed already$ git push -f
always pull with rebase
$ git pull --rebase origin master
to get forced pushes securely to rebase your commitsmaster
HEAD
TOPIC
STEP 2
ORIGIN/master
if you branch is pushed already$ git push -f
Sync source branch a!erwards$ git fetch origin master:master
perfect later make it single commit
$ git reset HEAD~3 or $ git rebase -i HEAD~3
HEAD
TOPIC
STEP 3
ORIGIN/master
tests are passing app is working code is reviewed (*)
master
$ git reset HEAD~3 (then commit) or $ git rebase -i HEAD~3
HEAD
TOPIC
STEP 3
ORIGIN/master
perfect later make it single commit
tests are passing app is working code is reviewed (*)
master
Use feature flags/toggles
HEAD
TOPIC
STEP 4
ORIGIN/master
if feature should be disabled
merge back to source$ git checkout master $ git merge topic
master
Use feature flags/toggles
master
HEAD
TOPIC
STEP 4
ORIGIN/master
if feature should be disabled
merge back to source$ git checkout master $ git merge topic
Continuous Integration validates master branch continuouslymaster
HEAD
TOPIC
ORIGIN/master
Pull requests can be used to review code and to validate before merging back to master
Scrum tasks are mapped to commits, not stories
Github Flow can be used to govern overall
TAMING THE POWER OF GITmake git the king again
Feature flags should be used whenever possible
Commit early & o"en perfect later, publish once philosophy
Deliver frequently be prepared to send every single commit
Deleting branches a"er merge will make your commit graph readable
use terminalGUIs are prison balls of developers
it’s ok to use GUIs while checking diffs, resolving conflicts and viewing commit graph
BUTTON ADDICT ANTI-PATTERN7
ANTIPATTERN DANGER
do not lose
take extra care while using hard reset
$ git reset --merge HEAD~
Use stash $ git stash save “updates local settings to keep db safe” $ git reset --hard HEAD~ $ git stash apply stash@{0}
Create a new branch $ git checkout -b feature/PA-121 $ git add settings.xml $ git commit -m “adds new settings config”
Use hard reset with merge
and commit into it
uncommited changes
CODE LOSING SYNDROME ANTI-PATTERN8
ANTIPATTERN DANGER
TOPIC
HEAD
MASTER
$ git merge --squash fix Squash commit -- not updating HEAD Automatic merge went well; stopped before committing as requested $ git add . $ git commit -m “adds a feature” $ git branch -D topic
TRASH HOUSE ANTI-PATTERN9
long living branches with carehandleANTIPATTERN DANGER
Squash all commits in your topic branch and make them available in working copy
long living branches with carehandle
TOPIC
HEAD
MASTER
$ git merge --squash fix Squash commit -- not updating HEAD Automatic merge went well; stopped before committing as requested $ git add . $ git commit -m “adds a feature” $ git branch -D topic
Squash all commits in your topic branch and make them available in working copy
stop adding
prevent commits from being big ball of mudsevery change
OMNIBUS BILL ANTI-PATTERN10
ANTIPATTERN DANGER
stop adding
prevent commits from being big ball of mudsevery change
local change sets at JetBrains IDEs
stop adding every changepartial add
messages areread!
# WHAT # <issue id> (this commit will...) <subject>
# WHY and HOW # Explain why this change is being made
# RELATED # Provide links or keys to any relevant issues or other resources
# REMEMBER # use lower case in the subject line # start with a verb in imperative tone in the subject line # do not end the subject line with a period # separate subject from body with a blank line # use the body to explain what and why vs. how # can use multiple lines with "-" for bullet points in body
$ git config --global commit.template ~/.git-commit-template.txt
$ git config --global commit.cleanup strip
use git commit templates to create be"er commit messages
comt
mi
F*CKING COMMIT MESSAGES ANTI-PATTERN11
ANTIPATTERN DANGER
messages areread!use git commit templates to create be"er commit messages
comt
mi
by adding new commits ?do you rollback your mistakes
ANTIPATTERN DANGER
12MESS UP WITH THE ROLLBACK ANTI-PATTERN
hard reset the merge commit$ git reset --hard HEAD~
if you haven't pushed yet
HEAD
MASTER
Bug fıx
never force push and change the history
if you already pushed to shared branch
Bug fıx
HEAD
MASTER
revert the merge commit$ git revert 8f937c6 -m 1
if you already pushedBug fıx
HEAD
MASTER
is not the only methodpushing commits to server
ANTIPATTERN DANGER
for sharing your code
13CENTRALIZED GIT ANTI-PATTERN
Git Pong Pairing
$ git remote add personA <URL> $ git fetch personA $ git checkout personA/master $ git checkout -b feature/PA-231 add your changes and commit $ git push personA feature/PA-231
A B
$ git checkout feature/PA-231 add your changes and commit
$ git pull personA feature/PA-231
with the ones in source branch ?
how do you sync your commits
ANTIPATTERN DANGER
14MERGE FANATIC ANTI-PATTERN
Bug fıx
ladder pa!ernoccurs when premature merge happens
HEAD
MASTER
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
c5
REPLAY #1
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
c5
REPLAY #2
c6c6
FIX
master
c1 c2 c3 c4 c7
HEAD
c5 c6c5 c6
use rebase $ git rebase master
c5
REWIND
c6c6
FIX
master
c1 c2 c3 c4 c7
HEAD
use rebase $ git rebase master
c5
FINALIZE
c6c6
deleting branches?are you scared of
ANTIPATTERN DANGER
15BRANCH CEMETERY ANTI-PATTERN
delete merged local branches$ git branch --merged | grep -v '^* master$' | grep -v '^ master$' | xargs git branch -d
delete remote branches$ git branch -r --merged | grep -v master | sed 's/origin\///'
| xargs -n 1 git push --delete origin
delete all merged local branches$ git branch --merged | grep -v '^* master$' | grep -v '^ master$' | xargs git branch -d
delete all merged remote branches$ git branch -r --merged | grep -v master | sed 's/origin\///'
| xargs -n 1 git push --delete origin
wri!en in any form?anyone can push any code
ANTIPATTERN DANGER
16UNCONTROLLED POWER ANTI-PATTERN
use pre-receive hooks
Depend on each otherToo many repositories
ANTIPATTERN DANGER
for sharing your code
17WEB OF REPOSITORIES ANTI-PATTERN
Mono Repository SystemEven though our services are still developed and deployed independently, the code for all services lives in one repository
The repository contains more than one logical project (e.g. an iOS client and a web-application)
These projects are most likely unrelated, loosely connected or can be connected by other means (e.g via dependency management tools)
Twi#er, Facebook, Google, Digital Ocean, Foursquare, Etsy, Shippable, Plataformatec, Ravelin
You can not do CI without using monorepos - Xebia
“When you start a new project,” Potvin tells WIRED, “you have a wealth of libraries already available to you. Almost everything has already been done.” - Rachel Potvin, Engineering Manager at Google
Our productivity has increased at least 5x. - Shippable
v1, v2, v3…having branch for every release
ANTIPATTERN DANGER
18ORACLE SYNDROME ANTI-PATTERN
at the same time
Commit early & o"en perfect later, publish once philosophy
Deploy frequently be prepared to send every single commit
Newer keep release branches for a long time master branch should be enough for all your needs
to git repoyou pushed confidential info
ANTIPATTERN DANGER
19WAITING FOR HACKERS ANTI-PATTERN
Ref: https://help.github.com/articles/remove-sensitive-data/
Do you know what evil merge is?
ANTIPATTERN DANGER
20EVIL MERGE ANTI-PATTERN
do you use feature branches when there is no product at all
ANTIPATTERN DANGER
21BRANCH OVERDOSE ANTI-PATTERN
use single branch topic branches simply make everything more
complex
Scared on using git commands
ANTIPATTERN DANGER
22CHUCKY THE COMMAND ANTI-PATTERN
push
add
dosya güncelleme
committed
Track ediliyor
untracked unmodified pushedmodifiedstaged
Staging Alanında Local Repoda Uzak Repoda
added
add
commitcommit
hard reset
committed
Track ediliyor
untracked unmodified pushedmodifiedstaged
Staging Alanında Local Repoda Uzak Repoda
added
hard reset
hard reset
mixed reset
mixed reset
soft reset
rm --cached
rmx
h"ps://github.com/lemiorhan/git-kata
no one knows git perfect do you suffer?
ANTIPATTERN DANGER
23NO HERO TO SAVE LIVES ANTI-PATTERN
have a git-man at least one developer should expertise on git
for supporting the others
Having duplicate commits &
Having irrelevant merge commits if you haven’t pushed yet
ANTIPATTERN DANGER
24DUPLICATE COMMITS ANTI-PATTERN
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5 c6
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5 c6
FIX
rebase and push
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5 c6
FIX
$ git rebase master
rebase and push
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
$ git push -f
rebase and push
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5 c6
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
pull rebased branch
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
$ git pull --rebase
pull rebased branch
UPSTREAMLOCAL
master
c1 c2 c3 c4 c7
c5 c6c5 c6
FIX
HEAD
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
c5 c6c5’ c6’
ORIGIN/FIX
$ git pull
pull rebased branch:(
UPSTREAMLOCAL
c1 c2 c3 c4 c7
c5 c6c5 c6
master
c1 c2 c3 c4 c7
c5 c6c5’ c6’
FIX
c5 c6c5’ c6’
c8
$ git pull
master
FIX
HEAD
ORIGIN/FIX
pull rebased branch:(
we commit when we have something big
ANTIPATTERN DANGER
25BIG FAT COMMIT ANTI-PATTERN
use TDD style whenever tests pass, commit
that makes you commit early and o!en
are you scared of using rebase?
ANTIPATTERN DANGER
26REBASE-FOBIA ANTI-PATTERN
rebasenot to merge your unpushed
commits with the fetched ones
use pull with
prepared by @lemiorhan
rebaseto get rebased commits from upstream safely
use pull with
REBASEfeature branches to integrate
into public branches
that you pushed or that you pulled
from another person
Never use Rebase
USE
do you know when we get conflicts and how to resolve it?
ANTIPATTERN DANGER
27CONFLICT-FOBIA ANTI-PATTERN
RECAP
what was reallyhappened at that time?
LET’S
master
TAG/v1.1
login
HEAD
DETACHED HEAD STATE
$ git checkout cecd95914 Note: checking out 'cecd95914'.
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.
LIVING AT DETACHED HEAD STATE ANTI-PATTERN28
ANTIPATTERN DANGER
master
TAG/v1.1
login
HEAD
DETACHED HEAD STATE
$ git rebase (and conflicts happen)
$ git checkout HEAD~2
$ git checkout 43e3ab01
$ git checkout tags/v1.1
WHEN IT HAPPENS
master
TAG/v1.1
login
HEAD
poor little developer...
master
TAG/v1.1
login
HEAD
$ git checkout master
master
TAG/v1.1
login
HEAD
$ git reflog
aa67e3a2c HEAD@{0}: rebase finished: returning to refs/heads/fix/java-sql-Date-violates-LSR aa67e3a2c HEAD@{1}: rebase: fixes UnsupportedOperationException while calling toIstant() method of java.sql.Date a45f3c4e5 HEAD@{2}: rebase: checkout develop 630ddad6e HEAD@{3}: checkout: moving from develop to fix/java-sql-Date-violates-LSR b26cf7a1a HEAD@{4}: rebase: checkout develop 630ddad6e HEAD@{5}: checkout: moving from develop to fix/java-sql-Date-violates-LSR b26cf7a1a HEAD@{6}: pull: Fast-forward 8b59f8f50 HEAD@{7}: checkout: moving from fix/java-sql-Date-violates-LSR to develop 630ddad6e HEAD@{8}: rebase: updating HEAD
$ git reflog
630ddad6ethe one we are
searching for
master
TAG/v1.1
login
HEAD
aa67e3a2c HEAD@{0}: rebase finished: returning to refs/heads/fix/java-sql-Date-violates-LSR aa67e3a2c HEAD@{1}: rebase: fixes UnsupportedOperationException while calling toIstant() method of java.sql.Date a45f3c4e5 HEAD@{2}: rebase: checkout develop 630ddad6e HEAD@{3}: checkout: moving from develop to fix/java-sql-Date-violates-LSR b26cf7a1a HEAD@{4}: rebase: checkout develop 630ddad6e HEAD@{5}: checkout: moving from develop to fix/java-sql-Date-violates-LSR b26cf7a1a HEAD@{6}: pull: Fast-forward 8b59f8f50 HEAD@{7}: checkout: moving from fix/java-sql-Date-violates-LSR to develop 630ddad6e HEAD@{8}: rebase: updating HEAD
master
typofix
TAG/v1.1
login
HEAD
$ git branch typofix 630ddad6e
master
typofix
TAG/v1.1
login
HEAD
$ git branch typofix 630ddad6e
KEEP CALM, NOTHING WILL BE LOST
LEMi ORHAN ERGiNagile software craftsman @ iyzico
/lemiorhan lemiorhanergin.com @lemiorhan
ANTIPATTERN DANGER