---
# System prepended metadata

title: Git Shit Done
tags: [' Talk', Git]

---

<!-- .slide: data-background="https://source.unsplash.com/842ofHC6MaI" -->

<!-- .slide: data-background-opacity="0.3" -->

# GIT SHIT DONE

---

### Who is this talk for?

- devs with (chronic) git pain
- all git users really
- you

---

<!-- .slide: data-background="https://source.unsplash.com/52QSSGA8Ej0" -->

##### Takeaway #1

Commits record state, not changes!

---

### Wait a second...

- <span style="color: grey; font-family: monospace; font-size: 95%;">git show</span> clearly shows me a diff
- <span style="color: grey; font-family: monospace; font-size: 95%;">git rebase</span> talks about applying commits
- what about <span style="color: grey; font-family: monospace; font-size: 95%;">git cherry-pick</span>?

---

### Commits, but simplified

- metadata such as author & message
- one or more parents (merge commits)
- filesystem state: trees and blobs

---

### Commands, but simplified

- diffs are always calculated
- commands often expand <span style="color: grey; font-family: monospace; font-size: 95%;">id</span> to mean <span style="color: grey; font-family: monospace; font-size: 95%;">id~..id</span>

---

### Rebasing, but simplified

- rebasing means running
    ```bash
    git format-patch id~..id
    git apply
    ```
- sequentially for each commit
- onto the target or the previous result

---

<!-- .slide: data-background="https://source.unsplash.com/0nOP5iHVaZ8" -->

##### Takeaway #2

Commits are referenced by different pointers

<br/>

##### (have a read some time: <span style="color: black; font-family: monospace; font-size: 85%;">man gitrevisions</span>)

---

### What's on the Menu:

- branch and ref names such as <span style="color: grey; font-family: monospace; font-size: 95%;">origin/main</span>
- <span style="color: grey; font-family: monospace; font-size: 95%;">@</span> or <span style="color: grey; font-family: monospace; font-size: 95%;">HEAD</span>
- generational selectors
    - <span style="color: grey; font-family: monospace; font-size: 95%;">~</span> selects the previous generation
    - <span style="color: grey; font-family: monospace; font-size: 95%;">^n</span> selects the n'th parent
    - <span style="color: grey; font-family: monospace; font-size: 95%;">~3</span> == <span style="color: grey; font-family: monospace; font-size: 95%;">&#94;1&#94;1&#94;1</span>

---

### What's on the Menu:

- commit message selectors
    - <span style="color: grey; font-family: monospace; font-size: 95%;">:/api</span>, <span style="color: grey; font-family: monospace; font-size: 95%;">:/^test</span>, <span style="color: grey; font-family: monospace; font-size: 95%;">:/!-feat</span>
- time and history based selectors
    - <span style="color: grey; font-family: monospace; font-size: 95%;">main@{yesterday}</span>
    - this is what's managed by <span style="color: grey; font-family: monospace; font-size: 95%;">git reflog</span>!

---

### Try those some time

```cpp
# edit last two commits
git rebase -i @~~

# look at your week so far (independent of commit time!)
git log main@{last monday}..

# graph some commits, add common parents and mark dupes
git log --graph --boundary --cherry-mark main...feature

# fixup the last commit that starts with test
git commit --fixup :/^test
```

---

<!-- .slide: data-background-opacity="0.3" -->

<!-- .slide: data-background="https://source.unsplash.com/-G1yhU1Ej-9A" -->

##### Takeaway #3

Review feedback does not need to be a single odd commit

<br/>

---

### Reviews and Atomic Commits

- Fixup allows us to add requested changes to the correct commit
- Autosquash those during <span style="color: grey; font-family: monospace; font-size: 95%;">rebase -i</span> (it's a config option)
- [git absorb](https://github.com/tummychow/git-absorb) determines the fixup targets automatically!

---

### Absorbing Commits

1. Given a change <span style="color: grey; font-family: monospace; font-size: 95%;">A</span>, calculate a patch <span style="color: grey; font-family: monospace; font-size: 95%;">B</span> for <span style="color: grey; font-family: monospace; font-size: 95%;">@~..@</span>
2. Apply onto <span style="color: grey; font-family: monospace; font-size: 95%;">@~</span>
    - first <span style="color: grey; font-family: monospace; font-size: 95%;">A</span>, then <span style="color: grey; font-family: monospace; font-size: 95%;">B</span>
    - first <span style="color: grey; font-family: monospace; font-size: 95%;">B</span>, then <span style="color: grey; font-family: monospace; font-size: 95%;">A</span>
3. Equal results? <span style="color: grey; font-family: monospace; font-size: 95%;">A</span> and <span style="color: grey; font-family: monospace; font-size: 95%;">B</span> **commute**
    - reset <span style="color: grey; font-family: monospace; font-size: 95%;">@</span> to <span style="color: grey; font-family: monospace; font-size: 95%;">@~</span> and goto 1.
4. Different results? Fixup commit <span style="color: grey; font-family: monospace; font-size: 95%;">x</span>, next change

---

### Thank you! :rocket: 