Git Panic

and how to avoid it

Alternative tite:

Cool tricks you learn
if you actually read the manual

*Disclaimer: basic git knowledge required

About me:

  • Hi, I'm Mihail Mikov
  • Full-stack engineer at Skyscanner
  • Hobby juggler

          git config --global user.name  "Mihail Mikov"
          git config --global user.email "mmikov@aubg.edu"
        

Git is hard

git is hard meme with jackie chan

Git Panic symptoms

  • Fear of the console / GUI only
  • Unstructured / messy history
  • Complicated / blocking workflow
  • Fixing git by cloning to a new repo

Git Panic symptoms

  • Push races / lots of conflicts
  • Lost local changes
  • Lost remote commits

So, how do I fix my git?

Bad solution: Panic

Solution

Pure Vegan Homeopathic solutions

  • Read the manual
  • Use the console
  • Check your status and history often
  • Fetch remotes often
  • Push your WIP often

Pure Vegan Homeopathic solutions

  • Follow a commit message format
  • Name remotes and branches meaningfully
  • Make git help you:
    • Aliases
    • Tags
    • Hooks
    • Command options

About commands


          commandName --options arguments
        
Command Types:
    • Local
    • Remote
    • Pluming
    • Porcelain

Command scope

Project history

Use a short, but detailed graph view of your history

          git log --all --graph --format="%h %d %an %cr %s"
          git log --author="Your Name" --since="3 weeks ago"
          git log master...my-branch --left-right
          git log --stat -p
        

Commit ranges

double vs triple dot ranges

Branch history

Useful for finding things you were working on

          # show a history of the commits
          # the given branch was pointing to
          git reflog <branch>
        

Referencing commits

The many ways to refer to commits

          # exclude commit and its ancestry
          ^master

          # the 2nd ancestor of the given commit
          master^^
          master~2

          #the 2nd parent of the current commit
          master^2
        

Referencing refs


          # the 3rd commit in the log of the ref
          master@{2}

          # the commit the ref pointed to at the given date
          master@{5.days.ago}
        

File history

Don't blame the player, blame the game

          # show who and when last modified each line of a file
          git blame --date=relative <file-name>

          # show the detailed history of a file
          git lg -p -- <file-name>
        

Adding something specific

Stage your changes and create your commits with care

          git add -p
        

Clearing the index snippet by snippet

That shouldn't be in your next commit

          # unstage changes from the index
          git reset -p
        

Make that snippet great again

Bring back an older version of the snippet

          # pick and override snippets in the working tree
          git checkout -p <commitish> <file-name>
        

Checkout the code

Checkout does a lot of things

          # checkout a branch you previously worked on
          git checkout @{-1}

          # create a new branch and switch to it
          git checkout -b "new_branch"

          # like "-b" creates a branch, but the first commit
          # on this branch will start an independant history
          git checkout --orphan "separate_history"
        

Detached head

A scary name for "you are not on any branch"

          git checkout <branch>
          # HEAD is pointing to a branch
          # which is pointing to a commit

          git checkout <commit>
          # HEAD is pointing directly to a commit
        

Unpacking commits

You don't need to rebase to squash your commits

          # make HEAD point to a specific commit
          # without changing the index or the working tree
          git reset --soft <commitish>
        

Moving our HEAD around


          # both HEAD and the current branch
          # will point to the given commit
          git reset --hard <commitish>
        
deletes changes in the index and working tree
may lead to disconnected commits

Undo some changes

without rewriting history

          # creates a commit that negates the changes
          # introduced in another commit
          git revert <commitish>
        

"Moving" a single commit around


          # creates a new commit at HEAD with the
          # same changes introduced by another commit
          git cherry-pick <commitish>
        

"Moving" many commits around


          # as if you cherry-picked
          # all the commits on a brach in order
          git rebase <new-base> <target-defaults-to-HEAD>

          # interactive rebase
          git rebase -i

          # rebase instead of creating a merge commit
          git pull --rebase
        

Rebase in action

Setting up Aliases

Common tasks should be easy to perform

          git config --global alias.co "checkout"
          git config --global alias.br "branch --verbose"
          git config --global alias.up "pull --rebase"

          git config --global alias.lg
            "log --graph --format='%h %d %an %cr %s'"

          git config --global alias.quickfix
            "commit -p --amend --no-edit"
        

Conflicts? Just ignore 'em

Resolving conflicts

Conflicts appear when git cannot merge
the content of two versions of a file meaningfully

          # abort if you can't solve the conflicts
          git <merge | rebase | cherry-pick> --abort

          # Warning: the meaning of --theirs / --ours
          # is different between merge and rebase

          # finish the operation with "--continue"
          git add <resolved-files>
          git <merge | rebase | cherry-pick> --continue
        

Common workflows

  • All in master
  • Team / Feature branches
  • Merge / Pull requests

Fetch, compare, rebase

A pull is just a fetch and a merge

          git fetch <remote> <branch>

          # show a graph of all commits
          # since the last common point between the branches
          git lg --left-right HEAD...<remote/branch>

          # rebase your changes on top of the remote
          git rebase <remote/branch>
        

Safe force push


          # only re-write the remote's history
          # if you already have a local copy of it
          git push --force-with-lease

          # alias: git sfp
        

Merge, but no fast-forward


          # Rebase and merge to keep the branch history visible
          git rebase feature_branch master
          git merge feature_branch --no-ff
        

Recap & takeaways

  • Use the console
  • Name remotes, branches and commits meaningfully
  • Keep your workflow & history understandable
  • Fetch and push often
  • Read the manual
  • Make git help you

Questions?!

Thank you!