Git Anti-Patterns: How To Mess Up With Git and Love it Again

  • View
    1.221

  • Download
    0

  • Category

    Software

Preview:

Citation preview

LEMi ORHAN ERGiNagile software craftsman @ iyzico

GIT ANTIPATTERNS

How To Mess Up With Git and Love It Again

/lemiorhan lemiorhanergin.com @lemiorhan

meetup.scturkey.org agileturkey.org

dev.iyzipay.com

GIT

LEMi ORHAN ERGiNagile software craftsman @ iyzico

agile practice lead at iyzico developing software since 2001

worked at Sony, eBay/GittiGidiyor, ACM consultant, architect, mentor, developer

founder of Software Craftsmanship Turkey ex community leader of Agile Turkey

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 ?

learn how git worksno worries, I will cover how git behaves

the way it keeps FILES & FOLDERSworking copy staging area objects database repository

the way it keeps REFERENCES

directed 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 “initial 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 “initial 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

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

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

are you sure?

are you brave enough tojump to any commit ?

do you haveloooooong living

topic branches ?

ANTIPATTERN DANGER

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…

before mergingdo you validate commits

back to source ? are you sure?

merge and unmergedo you o!en want to

just before releases ?

ANTIPATTERN DANGER

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

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 single 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

Any Other Cures?

use terminalGUIs are prison balls of developers

it’s ok to use GUIs while checking diffs, resolving conflicts and viewing commit graph

do not losetake 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

TOPIC

HEAD

MASTER

long living branches with carehandle

Squash all commits in your topic branch and make them available in working copy

$ 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

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

stop adding

prevent commits from being big ball of mudsevery change

local change sets at intelliJ

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

.git-commit-template.txt

use git commit templates to create be"er commit messages

comt

mi

messages areread!use git commit templates to create be"er commit messages

comt

mi

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.

master

TAG/v1.1

login

HEAD

DETACHED HEAD STATE

(login)$ git rebase master First, rewinding head to replay your work on top of it... Applying: settings Using index info to reconstruct a base tree... Falling back to patching base and 3-way merge... Auto-merging settings CONFLICT (add/add): Merge conflict in settings error: Failed to merge in the changes. Patch failed at 0001 settings The copy of the patch that failed is found in: .git/rebase-apply/patch

(a16e6e8)$

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

630ddad6e

the 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

Recommended