1 of 24

Git Wizardry

Artificial Perfection

2 of 24

Hello World

Matt Fields

Systems Programmer / Administrator

Identity and Web Services

Office of Information Technology

  • NC State History
    • Graduate of the NC State CSC program
    • Joined ITECS as a part time Web Developer in 2009
    • Full time in 2016, moved into Systems in 2018
    • Transferred to OIT-IWS in 2020
  • Primary Areas: CLS Linux, GitHub, Persona, WordPress

3 of 24

Wizards

“A Wizard is never late, nor is he early.

He arrives precisely when he means to.”

4 of 24

A Common Comparison

The upper echelon of programmers are often jokingly referred to as “Wizards”, seemingly making the impossible happen and writing perfect code that lesser mortals dream to one day achieve.

How do they do it?!?

5 of 24

Magic

Use the Book of Spells to warp reality and rewrite time!

Bag of Holding, Spell Sculpting!

6 of 24

Well let’s learn some Magic!

Rewrite history to fix mistakes before they happen!

Move ideas and reorganize thoughts!

Remove clutter and mess and present the illusion of perfection!

7 of 24

Our Spell Book

Add Patch - Cantrip

Amend Commit - Level 1

Stash - Level 2

Cherry-pick - Level 3

Rebase - Level 4

Filter-Repo - Level 5

8 of 24

Add Patch

git add -p

Launches an interactive prompt to stage small chunks of changes, or leave them for a later commit.

Fantastic way to visually review changes and ensure everything makes sense to add into a commit.

9 of 24

Amend Commit

git commit --amend [-C HEAD]

Modifies the most recent commit by adding the currently staged changes, and optionally modifies the commit message. Use “-C HEAD” to skip editing the message.

Useful when you just need to add a small change into a commit, or need to slightly modify the commit message.

10 of 24

Stash

git stash / git stash pop

Stores all unstaged changes into the stash, which can later be restored to the current working directory.

Very useful when working on something and you need to switch branches to something else for a moment. Can stash multiple times for maximum multi-tasking.

11 of 24

Cherry-Pick

git cherry-pick <ref>

Plucks an individual commit from another branch/tag/commit and append it to the end of the current branch.

Useful when you have a change in one branch that needs to be incorporated into another branch, but the change hasn’t been merged into your mainline branch yet.

12 of 24

Bonus Action: Merge Conflicts

Getting comfortable with resolving merge conflicts will help a lot while manipulating history.

Often times moving a commit around to a different order will create a merge conflict that must be resolved to continue.

Keeping changes small helps avoid massively complicated merge conflicts, and they can be handled pretty quickly and painlessly.

13 of 24

Rebase

git rebase [-i] <ref>

Rewrites all commits since the given reference to the end of the graph. Optionally interactively decide which commits should be modified, combined, or deleted from the history.

The bread and butter for cleaning up history and reorganizing commits. Very powerful, but can cause damage if used carelessly. Better to practice in another branch at first.

14 of 24

Filter-Repo

git filter-repo <...>

The nuclear cannon of rewriting history. Provides a quick and easy way to extract folders into their own repository, fully delete files from history, and much much more.

Absolutely destructive if used carelessly, but enables things not possible with a simple rebase.

https://github.com/newren/git-filter-repo/

15 of 24

Awesome Combos

  • Add Patch / Stash / New Branch
    • Split in-progress work off into a separate branch�
  • Rebase / Commit / Checkout / Add Patch / Amend
    • Split a large commit in two�
  • Add Patch / Commit / Stash / Rebase
    • Forgot to add something as a part of an earlier commit

16 of 24

Turn This…

17 of 24

Into This…

18 of 24

Warning: Never Modify Known Reality

Mainline branches are sacred, and their history is immutable.

NEVER rebase, amend, or otherwise alter the history of a mainline branch unless you know exactly what you’re doing.

Modifying history on unpushed branches is fine and encouraged! You can’t break anything for anyone else because no one else knows those branches exist yet.

Modifying history on pushed, unmerged branches is acceptable as long as everyone working on that branch knows to expect changes.

19 of 24

Safely Force-Push Branch

git push origin <branch> --force-with-lease

Prevents overriding changes which came in since you checked out the branch.

If the push is aborted, try rebasing against the upstream and try again.

20 of 24

Live Examples!

21 of 24

Why Bother?

  • Smaller change sets are easier to test and review
    • Targeted CI/CD runs to only test what changed
    • Commits should explain thought process
    • 10,000 line change… LGTM!
  • Clean history makes finding changes easier
    • Adds context for the change
  • Ship changes faster
    • Small changes need less conversation

22 of 24

General Recommendations

  • Make liberal use of branches
    • New branches cost nothing, and are quick to revert. Use them to rewrite history safely.
  • Commit early and often
    • Smaller commits are easier to move around and manipulate.
  • Rebase your changes against main before submitting PRs
    • Ensures there are no conflicts, and keeps the history clean and easy to follow.
  • Rollup related changes where it makes sense
    • Branches with a large number of commits can be hard to reason about.
  • Keep branches targeted on a single small unit of work
    • You should ideally be able to describe a branch in a single sentence.

23 of 24

Questions?

24 of 24

GitHub Migration

Migration from github.ncsu.edu to Enterprise Cloud

  • Town Hall - Feb 24th@ 2:00 PM
  • Training Session - March 4th @ 3:00 PM
  • Biweekly Office Hours - Starting March 14th
  • Knowledge Base articles available in ServiceNow