Advanced git

Block 4.1: Advanced features of git

Jan Simson

Amending Commits ⏳️

  • Modify the last commit
    • Modify the commit message
    • Modify the commited changes
  • git commit --amend
  • VSCode: Possible via GitLens
    • Demo

Caution

Never do this if you already pushed the commit, as it will re-write history

Staging Parts Instead of Full Files 🧩

Instead of staging complete files, you can also stage just a section or selection of your changes.

  • CLI: Interactive Staging
    • git add --patch <file>
    • git add -p <file>
  • VSCode: β€œStage selected ranges”
    • Demo

Tags 🏷️

Background: https://giphy.com/gifs/stop-motion-experience-3oriNYjm7cl8MjpszK

What is a tag? 🏷️

You can tag a single commit in git.

  • Creates a named reference to this commit
    • Useful for versioning / releases e.g. v1.2.3
    • also e.g. course material: SS23, WS23
  • Can be checked out via git checkout <tag>
  • You can create a specific release for a tag
    • Attach changelog or artifacts
  • Can be useful for deployments if CD is not feasible

Creating a tag

  • CLI: git tag v1.2.3
  • VSCode: Commit > Create Tag (GitLens)
    • Demo

Note

Tags need to be pushed explicitly via git push --tags

Optional Practicals: Tags

  1. Creating a Release
    1. Tag the latest commit in your repository
    2. Push the tag to GitHub
      • You do not need to make a new commit
    3. Create a new release for the tag you pushed
  2. Go to learngitbranching.js.org
    1. Do Section "A Mixed Bag" > #4: Tags

Patches 🩹

Background: https://giphy.com/gifs/VeSvZhPrqgZxx2KpOA

Patches 🩹

Before platforms like GitLab/Hub existed, people collaborated by sending around patches via email.

A patch is essentially a commit exported as a file.

  • Create: git format-patch <commit/branch>
    • Will create .patch files for all commits till target
  • Apply: git apply <patch-file(s)>

Example Patch

From 265f0c1119113f0f84ebfc047c26ef39f5532e57 Mon Sep 17 00:00:00 2001
From: Jan Simson <git@simson.io>
Date: Wed, 15 Nov 2023 20:10:36 +0100
Subject: [PATCH 1/8] Update slogans

---
 docs/.vuepress/config.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 6c61bba..53a76bd 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -1,6 +1,6 @@
 module.exports = {
-    title: 'GitLab ❀️ VuePress',
-    description: 'Vue-powered static site generator running on GitLab Pages',
+    title: 'Advanced Git & Gitlab',
+    description: 'An interactive course where you get publish your own website',
     base: '/',
     dest: 'public'
 }
\ No newline at end of file
-- 
2.39.2 (Apple Git-143)

Practical: Creating Patches

  1. Navigate to a local git repository of your choice
  2. Get the latest commit hash
  3. Use git format-patch <id> to create a patch for it
  4. Examine the generated patch

Working with Large Files / Data: 🦣 git lfs

Git struggles with large binary files.

  • One possible solution: git lfs (large file storage)
  • Extension that needs to be installed separately
    • Install git lfs
    • Initialize once in each repository you want to use it in
    • Configure a pattern to specify which files should use it
  • Useful, but a bit annoying to use & debug
    • Alternatives exist: e.g. dvc

Stashing πŸ—„οΈ

What is Stashing? πŸ—„οΈ

  • Stashing allows you to temporarily store changes that are not ready to be committed yet.
  • Useful when you need to switch branches or perform other operations without committing half-done work.

Illustration of Stashes

How to Use Stashes?

git stash         # Stash changes
git stash list    # List stashes
git stash apply   # Apply the latest stash
git stash pop     # Apply and remove the latest stash

Or in a GUI e.g. VSCode (via GitLens)

Cherry Picking πŸ’

  • Apply a specific commit to your current branch
  • git cherry-pick <commit-hash>

Illustration of git chery-pick

Cherry Picking πŸ’

  • Apply a specific commit to your current branch
  • git cherry-pick <commit-hash>
  • Typically when branches are not merged
  • Can be useful for e.g. hotfixes πŸ›
  • Should not be overused
    • Usually full merges are the preferred solution

Interactive Rebases πŸ”₯

Besides normal rebases, you can also do interactive ones, where you get to decide what happens with each commit.

  • git rebase -i <target>
  • Super powerful + super dangerous
    • Easy to re-write history
  • Only use these when necessary or if you have a good backup

Interactive Rebases: Example 🧨

pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file

# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Taking a Closer Look: git bisect 🧐

  • You provide two references:
    • Last known commit where everything was well
    • Earliest commit that has the issue
  • Automatic search between both points
  • Great for pinpointing which commit introduced a bug πŸ›

Taking a Closer Look: git bisect πŸ”οΈ

git bisect start

# Current version is bad
git bisect bad

# 84571cf is known to be good
git bisect good 84571cf

# We get moved to a commit and examine it, it's bad
git bisect bad

# ... repeat with good / bad till we found the culprit ...

# End the git bisect session
git bisect reset

Working Trees 🌲🌳🌴

With git working trees, you can have different different branches from one repository checked out at the same time β€” each in a different directory

git worktree add <path>
  • <path> will be automatically checked for a matching branch / commit / tag
    • If none is found one is created
# Create a new directory *next* to the repository
# either checkout or create a branch my-feature
git worktree add ../my-feature

Questions?

Optional Practicals: πŸ’πŸ”₯

  1. Go to https://learngitbranching.js.org/
  2. Complete Section 3: "Moving Work around"
    • #1: Cherry Pick
    • #2: Interactive Rebase

End of Section πŸŽ‰

Any Questions?

[🏑 Back to Overview]

[⏩️ Next Section]