Git

🤔 WTF is it?

Sylvain Fankhauser

Liip

May 2017

Q: what are branches / tags?

A commit is identified by a hash

commit 66959dab20a37949828ac0502509656ac775f56d
Author: Sylvain Fankhauser <sylvain.fankhauser@liip.ch>
Date:   Wed Nov 30 13:32:30 2016 +0100
    
Remove duplicate import

A branch/tag is a shortcut to a commit

$ git rev-parse master
66959dab20a37949828ac0502509656ac775f56d

It is stored as a file in .git/refs/heads

And contains the hash it points to

$ cat .git/refs/heads/master
66959dab20a37949828ac0502509656ac775f56d

Q: what does git fetch do?

git fetch updates your remote branches & tags pointers

eg. origin/master

Q: how do I compare revisions?

git log master..origin/master

Show remote commits that are not in local master branch. That's how pull requests work!

git log master...origin/master

Show commits that are not common to both branches

Q: how do I commit a file?

Reset

Working tree ➝ index

Playing with the index

# add file to the index
git add [-p] path/to/file

# remove file from the index
git reset [-p] path/to/file

# stash status of working directory, including index (-u means include untracked files)
git stash [-u]

# stash status of working directory and index and give the stash a name
git stash save "WIP try to fix this mess"

# show contents of stash (-p means show the diff)
git stash show [-p]

# show the list of existing stashes
git stash list [-p]

# apply stash and remove it
git stash pop [stash@{n}]

My commit process

# add everything to the index
git add --all

# review changes
git diff --cached

# reset chunks if necessary
git reset -p path/to/file

# review changes
git diff --cached

# finally, commit with meaningful commit message (define a standard!)
git commit

Q: I can't push

To gitlab.liip.ch:tooyoo/tooyoo
 ! [rejected]        HEAD -> sprint-3/mdb-21 (non-fast-forward)
error: failed to push some refs to 'git@gitlab.liip.ch:tooyoo/tooyoo'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

git pull? git fetch? git merge? git rebase? git push --force?

Does it matter?

Interlude: what does push do?

Without argument, pushes to tracking branch

As set by --set-upstream-to and recorded in .git/config

Destination can be set explicitly

$ git push origin
$ git push origin master
$ git push origin master:newbranch # push master to newbranch
$ git push origin :newbranch       # delete newbranch

Q: what is a merge?

Fast-forward merges

      mdb-72
     /
A---B---C---D---E origin/mdb-72
A---B---C---D---E origin/mdb-72
                  mdb-72

Merged branch only has common ancestors with current branch

git merge [--ff-only] origin/mdb-72

Non fast-forward merges

      D---E mdb-72
     /
A---B---C
         \
          origin/mdb-72

Current branch has ancestors absent from merged branch

git merge [--no-ff] origin/mdb-72

      D---E---m mdb-72
     /       /
A---B---C---/
         \
          origin/mdb-72

Q: what is a rebase?

Rebasing avoids merges with local commits

Rebase

      D---E mdb-72
     /
A---B---C
         \
          origin/mdb-72

Replays non-common ancestors. This recreates commits!

git rebase origin/mdb-72

          D'---E' mdb-72
         /
A---B---C
         \
          origin/mdb-72

REBASING

KILLS

Be careful with rebase

  • Only rebase local commits
  • Never EVER rebase a merge commit because someday someone will notice and will come knocking at your door and bad things will happen

Q: enough with the warnings, how should I rebase?

Try to fast-forward merge first

[merge]
ff = only

[pull]
ff = only
rebase = false

Then either use git pull or git fetch + git merge

until...

fatal: Not possible to fast-forward, aborting.

 

Know what you rebase

It's dangerous to go alone! Take this:

[alias]
  incoming = "!git log ..@{u}"
  outgoing = "!git log @{u}.."
  inc = "!git incoming"
  out = "!git outgoing"

You don't want to break the repository

Make sure you know what you're rebasing with git outgoing

If git outgoing --merges outputs anything, DO NOT rebase!

DO NOT REBASE!

DO. NOT. REBASE!

Q: what about git pull?

git pull = fetch + merge

But it depends on your configuration

Q:

I SCREWED UP. STOP. SEND HALP. STOP. KTHXBAI. STOP.

--abort is your BFF

Works with merge and rebase

git reflog is your 2nd BFF

$> git reflog
83b206d HEAD@{0}: checkout: moving from sprint-4/mdb-20 to HEAD^
0e7b8ae HEAD@{1}: commit (amend): MDB-20 review fixes
051a6db HEAD@{2}: rebase finished: returning to refs/heads/sprint-4/mdb-20
051a6db HEAD@{3}: rebase: MDB-20 review fixes
83b206d HEAD@{4}: rebase: checkout refs/remotes/origin/sprint-4/mdb-20
753d540 HEAD@{5}: commit: MDB-20 review fixes
136b954 HEAD@{6}: commit (merge): Merge remote-tracking branch 'origin/sprint-4/master' into sprint-4/mdb-20

Combine it with the reset command

      D---E mdb-72
     /
A---B---C
         \
          origin/mdb-72
      D---E
     /
A---B---C
         \
          origin/mdb-72
          mdb-72

git reset --hard origin/mdb-72

Use show to view a specific version of a file

$ git show master:index.php

Best practices

1. Have a git expert

In case you screw up

2. Create atomic commits

add -p / reset -p / stash -p are your friends

3. Review git history during code review

Check for unrelated commits

4. Run tests after merging

You have tests, right?

5. Don't be afraid to merge

It's okay to merge an in-progress feature branch in your feature branch

6. Make it easy to run any revision of the code

Fixtures anyone?

7. Commit non-feature specific fixes on master branch

To make sure everyone benefits from them

8. Use --no-ff when merging into master

To keep track of the merge

9. Always refer to remote branch when merging

This will avoid problems when your local branch is not up-to-date

10. If you force push, use --force-with-lease

Your coworkers will thank you

11. Write meaningful commit messages

Use multiple lines!

commit 10016ebf1603d0771b50b61720efd7fbd311b688
Author: Sylvain Fankhauser <sylvain.fankhauser@liip.ch>
Date:   Mon Jan 9 15:50:33 2017 +0100

    KOMPRA-230 fix empty graphs
    
    If a competence layer doesn't have any children the outer bubble won't
    appear. That's probably because this piece of code was copy-pasted from
    StackOverflow and wasn't adapted.

12. Do not rebase pushed commits

Unless you're absolutely sure no one used them

13. Leave conflict mentions in commit message

They can help debugging if something goes wrong

Finally

Ask any question you have now 🤓

Thank you!

master

  1. Sprint 4 starts, Alice starts working on MDB-82 and creates a commit
  2. 1 day later, Bob starts working on MDB-83 which depends on MDB-82
  3. Alice finishes working on MDB-82 and requests a dev review
  4. Bob reviews Alice's work and merges it into
    sprint-4/master
  5. Chloe fixes an important bug in production, MDB-404
  6. Her commit is reviewed and merged into master
  7. master is merged into the current sprint branch

sprint-4/master

sprint-4/mdb-82

sprint-4/mdb-82

sprint-4/mdb-83

sprint-4/mdb-82

sprint-4/master

support/mdb-404

master

sprint-4/master

Team rawbot
workflow

Made with Slides.com