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]
# Show changes of a specific commit
> git diff [commit hash]~ [commit hash]
#   or alternatively
> git diff [commit hash]^!
# if it's not a merge-commit, you can also show 
# show the diff with the commit message with
> git show [commit hash]
# Compare two files from two commits
> git diff [commit hash]:[file] [commit hash]:[file]
# Compare the changes between two commits
> git diff [commit hash old] [commit hash new]
# Show stats of the changes between two commits
> git diff --stat [commit hash old] [commit hash new]
# 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]
# Reset Branch and Files to a previous commit:
> git reset --hard [commit hash]
# Reset Branch to a previous commit but keep all
# changes as "changes to be committed"
> git reset --soft [commit hash]
# 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]
# Text conflicts can be resolved manually.
# For binary files, grab the correct file:
> git checkout --theirs -- path/to/conflicted-file.txt
> git checkout --ours   -- path/to/conflicted-file.txt
# After resolving the conflict, add the selection to the merge commit
> git add path/to/conflicted-file.txt
# 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
## Tags
# List tags
> git tag
# Create tag
> git tag -a [tag_name]                    # Creates tag
> git tag -a [tag_name] -m "[annotation]"  # Creates tag with annotation
# Show tag info
> git show [tag_name]
# Push tag to remote
# (by default, git push does not push tags)
> git push origin [tag_name]   # Push a single tag
> git push origin --tags       # Push all local tags
# Delete tag locally
> git tag -d [tag_name]
# Delete tag on remote
> git push origin --delete [tag_name]
# Checkout tag (either of these work)
> git checkout [tag_name]
> git checkout tags/[tag_name]
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_HEADcherry-pick: git rev-parse --verify CHERRY_PICK_HEAD
Remove --global to make changes local to a repository:
# Initial git configuration
> git config --global user.name "Your Name"
> git config --global user.email "Your@Mail.com"
# Change default branch name
> git config --global init.defaultBranch main
# When working with submodules, automatically update when updating a branch
> git config --global submodule.recurse true
# For multiple operating systems: 
# If the different line endings are making problems, 
# consider setting "autocrlf" to "true" or "input"
> git config --global core.autocrlf input
# Signing
# Enable commit signing
> git config --global commit.gpgsign true
> git config --global tag.gpgSign true
# Use GPG keys: List keys and use from key ID 
# Example key ID: 3AA5C34371567BD2
> gpg --list-secret-keys --keyid-format=long 
> git config --global user.signingkey [Key ID]
# Use SSH keys
# Example key location: /home/myUser/.ssh/id_rsa.pub
> git config --global gpg.format ssh
> git config --global user.signingkey [Path to Key]
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 not_ present, do:
> git bisect good
# If the bug _is_     present, do:
> git bisect bad
# If the commit is not testable, do:
> git bisect skip
# 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
# NOTE: 
#   You can use git bisect to find when a bug has been fixed,
#   but git bisect is designed to find regressions.
#   Therefore when finding the fix, you have to use 
#     "git bisect bad"  when the bug was fixed, and
#     "git bisect good" when the bug is present.
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]