Git

Based on ThePrimeagen’s “Everything You’ll Need to Know About Git” course on Frontend Masters

https://theprimeagen.github.io/fem-git/

Config

git config --list
git config --add user.name "itsme"
git config --add user.email "itsme@email.com"
git config --get user.email # only shows the last added value
git config --get-all user.email
git config --get-regexp us
git config --unset init.defaultBranch # doesn't work for multiple values
git config --unset-all 
git config --remove-section user

Aliases

# git author <hash> to get author name and email of commit
git config --global alias.author "show -s --format='%aN: %aE\'"

Creating a repo

git init

Cloning a repo

git clone <url>

Submodules

cd to any one submodule # not sure if needed
git submodule init
git submodule update

If a repo required git clone --recursive, but you cloned normally:

git submodule update --init --recursive

Creating a commit

git add .
git commit -m "message"

Updating the last commit (rewrite history)

git commit --amend

Viewing the commit history

git log --oneline --graph
git log -4 # last 4 commits

Reading contents of a SHA

A SHA may be linked with a commit, file, tree (folder), etc.

git cat-file -p <sha>

It’s enough to only enter the first 7 digits of the SHA.

Branching

git branch # view the branches
git branch foo # create a branch foo
git checkout foo # switch to branch foo
git checkout -b foo # create branch foo and checkout

To delete a branch

git branch -d foo # branch must be merged to origin or HEAD
git branch -D foo # shorthand for -d --force

Merging branches

git merge otherbranch

If both branches diverged, it will create a new ‘merge commit’. If only otherbranch diverged, then it’s newer commits are copied to the current branch (called a Fast-Forward merge).

Rebasing

  1. execute git rebase <targetbranch>. I will refer to the current branch as <currentbranch> later on
  2. checkout the latest commit on <targetbranch>
  3. play one commit (diff) at a time from <currentbranch>
  4. once finished will update <currentbranch> to the current commit sha
   B --- C                foo
 /
A --- D --- E --- X --- Y trunk
                           B --- C                foo
                         /
A --- D --- E --- X --- Y                         trunk
git checkout foo
git rebase trunk

Interactive Rebase

Tip

HEAD~1 means one commit back from HEAD

git rebase -p <parent of last commit to rebase till>

The one line commit messages shown are only for our convenience.

Options

Commits can be reordered, their diffs are what get applied.

Warning

Rebasing will change the commit SHA of the modified commit, and all commits after it. Only use rebase for commits that other developers have not pulled. Ideally, only use it with commits you haven’t yet pushed.

Reflog

HEAD is a reference to the current branch. Reflog shows you where HEAD has been. It kind of shows the history of your Git actions.

git reflog 
git reflog -3 # see last 3 lines

Cherry Pick

Take just one commit’s diff from another branch and add it to the current branch:

git cherry-pick <commit-sha>

Remote

To add a remote

git remote add <name> <uri>

To view remotes with their uris

git remote -v # verbose

Naming conventions:

Fetch

This will get information about remote branches. Does not actually make any changes to local branches.

git fetch

Then it is possible to see the logs of the branches that were fetched:

git branch -a # view all branches, including remote ones
git log origin/main

Commits from remote branch can be merged into local branch

git merge origin/main

Fetch a Pull Request

git fetch upstream pull/1234/head:local_branch_name

Or,

git checkout -b danferns-tuning_color_fix main
git pull git@github.com:danferns/mixxx.git tuning_color_fix

Pull

Perfoms fetch and merge automatically.

To link the local branch to the remote one (tracking info)

git branch --set-upstream-to=origin/main main

Pull changes from remote

git pull # pull based on tracking info
git pull origin main # pull from specific remote branch
Pull with rebase

May be preferred over merge, because it keeps the local changes at the top of the git log.

git pull --rebase

There is also a pull.rebase true global config option to do this by default

Push

Copies changes from local branch to remote branch

git push

Force push may need to be done after a rebase, if it was done on already pushed commits.

git push --force

Now the remote branch’s history will be replaced with the local branch.

Stash

Push to stash stack

git stash
git stash -m "friendly message"

See the stash stack

git stash list

See the changes to files in a specific stash

git stash show 
git stash show 1 # show files changed in stash@{1}
git stash show --index 1

To pop a stash

git stash pop
git stash pop --index 1

Reuse Recorded Resolutions (rerere)

Git remembers how you resolved a previous merge conflict.

When pulling with rebase, you may have to deal with the merge conflict again.

rerere is an option that remembers how a previous merge conflict was handled, and reuses it automatically.

git config rerere.enabled true

If you incorrectly resolved a conflict, you should delete the rerere’s.

Ours and Theirs

Resolve a merge conflict by only taking ours or their changes

git checkout --ours README.md #use "ours" change
git checkout --theirs README.md #use "theirs" change

Revert

Used to record some new commits to reverse the effect of some earlier commits (often only a faulty one)

git revert <commit>

Tags

Adds a tag to HEAD:

git tag -a 1.0.4 -m "1.0.4"

Removes a tag:

git tag -d 1.0.4

Ignore Files Locally

The .git/info/exclude file has the same format as any .gitignore file. Another option is to set core.excludesFile to the name of a file containing global patterns.