The art of version control
git config --global color.ui true
Graphing -------- Option 1: use external software like SourceTree or Tower Option 2: `gitk` Option 3 (the cool way): `git log --graph --all --oneline --decorate` (you might want an alias) Bonus: try adding `--simplify-by-decoration` to the above Tip: add `-- path/to/file.ext` to any git log command to only see commits that changed that file (even if the file isn't in your working tree!)
Q: Which colour line represents the "dev" branch?
A: Trick question! Branches are pointers to a single commit only.
Git graphs aren't trees, they are more like linked-lists.
Branches are merely references to the "loose ends."
The correct question is: "Which commits are down-stream from the commit referenced by the dev branch?"
(A: ALL of them, except fix_hook and forgery)
Comparing commits (.. vs ...) ----------------------------- `git log master..dev` = "What commits are unique to dev?" --or-- "What commits are reachable from dev, but not from master?" `git log featureA...featureB` = "What commits are reachable from either featureA or featureB, but not both?" Bonus: * Use `--left-right with` ... * Use `-p` or `--stat` to see changes by commit * Use `git merge-base A B` to find the common commit between branches * Use `..remote-name/branch-name` to compare to remotes * Leave out either side of the ... to mean "use HEAD" * Use `branchX..abc123` to find out if a branch has a specific commit in it (an empty result means it does, otherwise it doesn't) Gotcha: git diff is different (see next slide)
Comparing code -------------- `git diff A B` (or `git diff A..B`) to diff revisions `git diff A...B` to see only diffs added by B `git diff` to see diffs between working directory and index `git diff --cached` to see diffs between staged files and index Tip: use `git diff` and `git diff --cached` before a git commit Tip: git pipes its output through less, so you can search with `/pattern<enter>` and use `n/N` for next/previous.
grep in git! ------------ `git log --grep pattern` to search commit messages `git grep -n pattern` to search index Bonus: `git grep --help` for advanced searching `git log -Spattern` to search diffs (see when you made changes to 'pattern')
Tracking down where things went wrong ------------------------------------- git bisect to the rescue! `git bisect --help`
git knows what you've done -------------------------- Have you ever lost your commits after a rebase, reset, stash, etc? The good news: No, you have not. `git reflog` There they are :)
You can change the state of your code in 2 ways:
1. Move yourself to the code
2. Bring the code to you
Move yourself to the code: * `git checkout branchName`
Tip: relative refs are useful.
* `git reset HEAD~3` to go back 3 commits (brings your working directory with you unless you add `--hard`)
Bring the code to you:
* `git merge branchName` (add `--no-commit` to make edits first)
Tip: `git add -i` or `git add -i` for partial committing.
Tip: `git mergetool` makes resolving merge conflicts much more fun. Tip: Remember you can grab code from different remotes too.
* `git checkout abc123 -- path/to/file.ext` (add `-p` for super fine control extra awesomeness)
Why change history? To clarify your story of development. * Clarify commits * Clarify messy branches Warning! Do not change history of public commits. * `git commit src/fileIForgotToAdd.js --amend` (plus you can edit the commit message) * `git reset HEAD~`, then `git add -i` if you commit too much * `git reset ref` to change where your branch references (like resetting your messed up local branch to the version on the remote) And of course, our good friend, Mr. Rebase! (He's not so scary)
(maybe a little scary)
Rebasing: moving branches around -------------------------------- Who cares?: I do!! Why?: They keep the history nice and flat: * Avoid unintentional and unnecessary merge commits * Correct haphazard branching-off points Simply defined: `git rebase master feature` = "Remake all of the commits in `git log master..feature`, in order, one by one, off of the tip of master." (Remember the warning: no rebasing public commits)
Neat Rebase tricks ------------------ * `git rebase --onto X A B` to rebase A..B onto X instead of the tip of A. This is useful if you branched a feature off of a feature and want to move it to the main trunk (`git rebase --onto master featureA featureB`). * Add `-i` for interactive rebasing (you get a chance to massage each commit before it gets remade). Great for commits like "wip", "oops, forgot to update README" and "spelling fix." But also: `git rebase HEAD~5 -i` to clean up the last 5 commits. * `git pull --rebase` instead of git pull if your local branch has diverged from its upstream tracking branch. Instead of creating a "merge origin/dev" commit, it will pull in the remote branch and rebase your local commits onto the tip of it.
Thank you