A Graceful Guide to Git

October 14, 2021

Overview

Basic Commands

Configuration

  • git config --global user.name <username> - set username
  • git config --global user.email <email> - set email

Initialising A Repo

  • git clone [https://github.com:ACCOUNT/REPO.git](https://github.com:ACCOUNT/REPO.git) - clone repo from GitHub
  • git init -b main - create repo locally in current working directory

Staging Changes

When working with git, there are 3 components to think about:

  • Working directory (all your local files and folders)
  • Staging area (all file changes tracked by git, but not yet saved by git)
  • Git directory (all changes saved by git)

With this structure, git recognises the state of a file in the working directory as either: untracked, unmodified, modified or staged. When you add a file to your working directory, you use git to track them. When you modify a file, you use git to stage them. Once you have staged the changes you want to make, you use git to commit these stages. These commits may be used to look back in time at previous versions of your code (and lots more).

  • git add . - stage all files (current directory)
  • git add --all - stage all files (current + sub directories)
  • git add \_.py - stage all files by wildcard (current directory)
  • git add \*\*/\_.py - stage all files by wildcard (current + sub directories)

Committing

  • git commit -m "<commit_message>" - commit all staged changes
  • git commit --allow-empty -m "<commit_message>" - commit an empty change

Viewing Git Information

  • git status - show working directory and staging area
  • git log - show commit history for CURRENT branch
  • git log --all - show commit history for ALL branches
  • git log --author="Author Name" --oneline - show commit history for particular author
  • git ls-files -s - show which files have been staged
  • git rev-parse HEAD - view current commit hash
  • git shortlog -sn | head -3 - view top contributors for a repo

Intermediate Commands

Branching

Viewing branches:

  • git branch -a - view all branches (local and remote)
  • git cherry -v main <branch_name> - view change in commit history between branches

Creating branches:

  • git branch <branch> - create new branch
  • git checkout <branch> - checkout new branch
  • git checkout -b <branch> - create and checkout new branch

Deleting branches:

  • git branch -d <branch> - delete branch on local
  • git push origin --delete <branch> - delete branch on remote
  • git fetch -p - pull updates from remote-tracking branches and prune remote branches if they have been deleted
  • git remote update origin --prune - update local list of remote branches

It doesn't matter which branch you are on when staging changes, it only matters when these changes are committed (ie: stage files on whatever branch, but make sure to commit those changes on the desired branch).

Merging Changes

Create a feature branch to work on your code modifications. Once you are happy with the changes, you want to merge these back into the main branch.

  • git checkout <branch>
  • make changes, stage files, commit stages
  • git checkout main
  • git merge <branch>
  • resolve any conflicts, stage changes, commit stages

Setting an Upstream Branch

Setting an upstream (where a local branch tracks a remote branch) makes pushing/pulling easier and allows you to see any unsynced commits between the two.

  • git remote add origin [https://github.com:USER/PROJECT.git](https://github.com:USER/PROJECT.git) - add remote branch for repo USER/PROJECT
  • git remote -v - check remote branches
  • git branch -u origin <local_branch> - set upstream branch
  • git push -u origin <local_branch> - set upstream branch when pushing changes (this is equivalent to above)

Create local branch to match remote branch:

git switch <remote_name>

Merge remote git repository into unrelated local git repository

git pull origin main --allow-unrelated-histories

Working Remotely

  • git push -u origin main - push local changes to remote repo and set upstream branch
  • git push - once you've set an upstream branch, you can use the following shorthand
  • git pull origin main - pull remote changes into local repo
  • git pull - once you've set an upstream branch, you can use the following shorthand

Configuration:

  • git remote set-url origin git@github.com:<USERNAME>/<REPOSITORY>.git - change remote URL to use SSH

Removals:

  • git remote rm <remote_name> - remove remote branch from being tracked
  • git push -d <remote_name> <branch_name> - delete remote branch

Removing Files from Git

  • git rm <file_name> - remove files from git directory AND working directory
  • git rm --cached <file_name> - remove files from git directory ONLY
  • git rm --cached -r <directory_name> - remove directory from git directory ONLY

Stashing

  • git stash show - show current stashed modifications
  • git stash -m "Stash message" - push current uncommitted changes to the stash log
  • git stash pop - pop the most recent set of stashed changes

Command Cookbook

Global Configuration

Create a .gitconfig file to configure global credentials, settings and aliases across all git repositories:

[user]
    name   = Luke Miloszewski
    email  = lukemiloszewski@gmail.com
[github]
    user   = lukemiloszewski
[init]
    defaultBranch = main
[core]
    pager = cat
    editor = code --wait
[color]
    ui = auto
[color "branch"]
    upstream = cyan
[log]
    abbrevCommit = true
    follow       = true
    decorate     = false
[tag]
    sort = version:refname
[alias]
    aliases  = !git config --get-regexp alias | sed -re 's/alias\\.(\\S*)\\s(.*)$/\\1 = \\2/g'
    a        = add
    cm       = commit -m
    s        = status
    p        = push
    pom      = push -u origin main
    puom     = pull origin main
    co       = checkout
    cob      = checkout -b
    fp       = fetch --prune --all
    lg       = log --graph --date=relative --pretty=format:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset'
    reword   = commit --amend
    uncommit = reset --soft HEAD~1
    untrack  = rm --cache --

Amending the Last Commit

There may be times when you commit changes and realise that you forgot something important that you wanted to include in the snapshot. You can amend the most recent commit to include the changes you made.

  • git commit -m "Commit message"
  • git add <filename>
  • git commit --amend -m "Updated commit message" - change most recent commit message

Use git commit --amend --no-edit if you don't need to change the commit message.

Post-Merge Workflow

Once you've closed a pull request and merged a feature branch into the main branch, you can delete that feature branch both locally and remotely (ie: the branch is not needed, you don't need your local machine nor the remote server to keep a reference to it).

On GitHub:

  • Close the pull request and merge the feature branch into your main branch
  • Delete the feature branch (you should be prompted to do so after closing a PR)

On local machine:

  • git checkout main
  • git pull
  • git fetch -p
  • git branch -d feature_branch_name

You may receive a warning that prevents you from deleting the local branch if you have changed any commit messages in your PR (ie: if you've squashed any commits). In this case use the -D flag which will force delete the branch. Just make sure all necessary changes have been pulled in.