Git
Based on ThePrimeagen’s “Everything You’ll Need to Know About Git” course on Frontend Masters
https://theprimeagen.github.io/fem-git/
Config
- All git config keys are in the following shape:
<section>.<keyname> - The config is just a file,
.git/config --globalflag will use a global file for all repos- A key may have multiple values
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
- execute
git rebase <targetbranch>. I will refer to the current branch as<currentbranch>later on - checkout the latest commit on
<targetbranch> - play one commit (diff) at a time from
<currentbranch> - 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
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
editto have rebase stop at the commit. You can make changes to files, add more commits, or dogit commit --ammendto change the commit messagerewordto directly change commit messagefixupcombines a commit’s diff with the previous one, keeping previous commit’s messagesquashcombines with prev. commit, but allows editing the combined commit message
Commits can be reordered, their diffs are what get applied.
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
- a remote is a copy of the repo somewhere else (can also be another folder)
To add a remote
git remote add <name> <uri>
To view remotes with their uris
git remote -v # verbose
Naming conventions:
- If you are working on a fork, the fork repo is
origin, and the original project repo isupstream - If you’re not on a fork, the repo is simply
origin(source of truth repo)
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
May be preferred over merge, because it keeps the local changes at the top of the git log.
git pull --rebaseThere 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.