Resources:
# Setup a repository
> git init
> git remote add origin ssh://user@website/blah.git
> git status # List changes / status
> git add [File to push] # Add changes
> git commit -m "[message]" # Finalize changes by adding a message
> git push -u origin main # Initial push.
# "git push" is sufficient afterwards
# Edit commit message
> git commit --amend
# Move files / directories without losing the history
> git mv [to move] [new location]
# Add change onto already made commit
> git add [File(s) with small edit]
> git commit --amend --no-edit
# Show changes since last commit
> git diff
# Show changes of file since last commit
> git diff [path to file]
# Compare two files from two commits
> git diff [commit hash]:[file] [commit hash]:[file]
# Create and push a new branch
> git checkout -b [name]
> ... # Make changes to the branch
> git push -u origin [name]
# Switch branches
> git checkout [branch]
# Remove branches
> git push -d origin [branch] # Delete remote branch
> git branch -d [branch] # Delete local branch
# Temporarily remove changes
# (also possible if you want to temporarily switch branches)
> git stash
> ...
> git stash pop
# Pull changes/commits from another _remote_ branch
# onto the current one
> git pull origin [branch]
# Pull changes/commits from another _local_ branch
# onto the current one
> git pull . [branch]
# If you have the same repository in multiple directories,
# you can also pull the changes locally:
> git pull [path to repository]
# Undo a specific commit
# Find [hash] using git log, then:
> git revert [hash]
# Revert file to a specific commit
# Find [hash] using git log, then:
> git checkout [hash] -- path/to/fileA path/to/FileB
# _Completely_ discard all local changes
> git reset --hard HEAD
> git clean -d -f -i
# Merge changes from a branch onto main
> git checkout main
> git merge [branch]
# Rebase changes from a branch onto main
> git checkout [branch]
> git rebase main
# Remove a commit from your history before pushing
> git rebase -i HEAD~3 # List last 3 commits
# Opens a text editor. Now delete / modify the line of the commit
Sometimes git
refuses to do operations for seemingly no reason.
In practice, it might be that some operation is in progress without any indication.
bisect
: check if .git/BISECT_BEGIN
existsmerge
: git rev-parse --verify MERGE_HEAD
(or check if .git/MERGE_HEAD
or .git/MERGE_MSG
exists or if git merge HEAD
fails)rebase
: git rev-parse --verify REBASE_HEAD
(or check if .git/REBASE_HEAD exists
)revert
: git rev-parse --verify REVERT_HEAD
cherry-pick
: git rev-parse --verify CHERRY_PICK_HEAD
This is super useful if you e.g.
have your own personal version of a public project
in your own git
repo, but you want
to pull updates from the public project
if necessary.
In my case, I cloned the repo and adjusted the repo settings:
> git clone [link to original repo]
> git remote set-url origin [url to personal repo]
And then add the original repository back under another upstream name.
> git remote add [name] [link to original repo]
> git pull [name] [branch]
Now I can work on my local version
without having to constantly remind myself to specify
where to push to.
In my case, I added an upstream called "upstream".
In the rare occasion that I want to pull in updates
from the original repo, just
do git pull upstream master
.
Recently I started a project with a friend, and each wanted to host
an up-to-date repository on a local server.
For a very basic mirroring setup, you can configure a "main"
repository for your project, and setup your local git
repo
such that you git push
to all of your mirrors automatically.
Simply setup your local repository as follows:
> git init
> git remote set-url --add --push origin [link to main repo]
> git remote set-url --add --push origin [mirror 1]
> ...
While all of the main actions (e.g. git pull
) is done on the
"main" repository, you git push
will automatically also
push to each mirror.
git
has a built-in command/process such that
you can binary search for the commit
in which a bug was introduced:
# Identify
# - a "good" commit hash [goodHash] in which the
# error is not present, and
# - a "bad" commit hash [badHash] in which the
# error is present
# (use "git log" and "git checkout [hash]")
#
# Then start the bisect process:
> git bisect start
> git bisect good [goodHash]
> git bisect bad [badHash]
# Git will then repeatedly switch you onto
# other commits.
# If the bug _is present_, do:
> git bisect good
# If the bug _is not present_, do:
> git bisect bad
# After doing this a bunch of times,
# git will stop and tell you the commit
# in which the bug was introduced
[hash] is the first bad commit
...
# If you want to abort this process at any point:
> git bisect reset
Many git
commands have additional options,
which provide helpful visualizations and/or denser/quieter outputs.
As typing the args each time is annoying, you can either
configure your shell, or add aliases to git
directly.
Find out where your git config is:
> git config --list --show-origin
And then you can e.g. define aliases for common operations:
[alias]
# Overview:
#
# Parameter alias:
# testA = "commit -A"
# -> "git testA" becomes "git commit -A"
#
# Insert shell commands:
# testB = "!git log; git push"
# -> "git testB" becomes "git log; git push"
# Shorthand for simple projects
update = "!git add -A; git commit; git push"
update-no-push = "!git add -A; git commit"
# Shorthand for quieter/denser outputs
ll = "log --oneline"
llv = "log --oneline --graph --decorate"
st = "status -s -b"
c = "commit"
br = "branch -a -v"
co = "checkout"
cb = "checkout -b"
You can run automatically run a script
when a certain git
command is issued.
In your git
project, the script file needs
to be placed in ./.git/hooks/
with a name
specific to the command you want to hook into
(see here
for a list of hooks).
The folder also already contains a bunch of example
scripts.
Here is the pre-commit
-hook I use on programming projects.
It automatically formats files of a commit before it is finalized
(./.git/hooks/pre-commit
):
#!/bin/sh
# Get list of changed files
ARGUMENTS=$(git diff-index --name-only --cached HEAD)
# Run formatter on files
[YOUR_FORMATTER] $ARGUMENTS
# Assuming the formatter run without problems,
# add the changes to the commit
git add $ARGUMENTS
# Signal that hook ran successfully
exit 0
Don't forget: For very simple projects (e.g. updating this website), you can even automate / simplify your commits if aliases are not sufficient! For this website, I don't care about commit messages, and I keep have to add new posts/files to git. So I use the following script:
#!/bin/sh
# Overview pages
git add byName.html index.html
# Content pages
git add posts/
# Other
git add style.css Icon16.png Icon32.png
# Push
git commit -m "$(date)"
git push
# Assume you are currently in [original repo],
# [splitBranch] is just a name for the split
git subtree split -P [to move] -b [splitBranch]
# If you want to move the items onto a new repository
> cd [new repo]
> git checkout [your branch]
> git pull [path to original repo] [splitBranch]
# If you want to move the items into an existing repository
> cd [other repo]
> git checkout [your branch]
> git checkout --orphan [new temporary branch]
> git pull [path to original repo] [splitBranch]
# Do git mv here if you want to change the file / directory location
> git checkout [your branch]
> git merge --allow-unrelated-histories [new temporary branch]
> git branch -d [new temporary branch]