- Install Git distributed version control software.
- Set up your default credentials (or display without a value to set):
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
or if he's a GitHub user, so you see his icon: [email protected]
For example on MacOS:
~/Documents/code/test❯ git config --list
credential.helper=osxkeychain
init.defaultbranch=main
user.name=Cees Timmerman
user.email=c.timmerman@company
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
core.excludesfile=/Users/ct/.gitignore_global
core.autocrlf=input
difftool.sourcetree.cmd=opendiff "$LOCAL" "$REMOTE"
difftool.sourcetree.path=
mergetool.sourcetree.cmd=/Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"
mergetool.sourcetree.trustexitcode=true
commit.template=/Users/ct/.stCommitMsg
core.sshcommand=ssh -i ~/.ssh/myed25519key
~/Documents/code/test❯ cat ~/.gitconfig
[user]
name = Cees Timmerman
email = c.timmerman@company
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
[core]
excludesfile = /Users/ct/.gitignore_global
autocrlf = input
[difftool "sourcetree"]
cmd = opendiff \"$LOCAL\" \"$REMOTE\"
path =
[mergetool "sourcetree"]
cmd = /Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh \"$LOCAL\" \"$REMOTE\" -ancestor \"$BASE\" -merge \"$MERGED\"
trustExitCode = true
[commit]
template = /Users/ct/.stCommitMsg
[core]
sshCommand = "ssh -i ~/.ssh/myed25519key"
Generate a key with ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/myed25519key -C "For Git from MacOS."
and add the ~/.ssh/myed25519key.pub
content to your Bitbucket server keys for example.
Main or master is the (preferably working) development branch in most git branching models. (GitHub Flow, GitLab Flow, etc.; not Git Flow.) If you want to stabilize for a release, create a release branch and only merge bug fixes from master to it by cherry picking. When a branch works in your local environment (e.g. VirtualBox), rebase and push it to the remote. Ideally, merge requests should get reviewed and the remote production branch should get tested and deployed after it passes.
Check out new remote branch:
$ git fetch
$ git checkout -t origin/TICKET2 # Or `git switch TICKET2` since 2020.
Branch 'TICKET2' set up to track remote branch 'TICKET2' from 'origin'.
Switched to a new branch 'TICKET2'
And delete the old branch locally:
git branch -d TICKET1
Or if that complains:
git branch --delete --force TICKET1
Or create a new local branch and push it to remote:
$ git checkout -b TICKET2
Switched to a new branch 'TICKET2'
$ git add . # Stage all changes.
$ git reset DEBUG_FILE # Unstage this file.
$ git status # Verify changes.
$ git commit -m "MESSAGE"
$ git push -u origin TICKET2 # Note the lack of a slash.
Publish and track a new branch without getting a src refspec error:
git push -u origin HEAD:NEW_BRANCH_NAME
That -u
sets to track the new upstream branch just like this:
git branch -u origin/NEW_BRANCH_NAME
List all branches:
git branch -a
Rename local branch:
git branch -m NEW_BRANCH_NAME
Delete remote branch:
git push origin -d REMOTE_BRANCH_NAME
Remove remotely deleted branches from local remotes:
git fetch --prune
If you used https and are tired of entering your password, switch to git with a private key (after adding ssh-add ~/.ssh/id_ed25519
to your shell init):
git remote remove origin
git remote add origin [email protected]:project/components/subproject.git
git branch -u origin/TICKET TICKET
Alternatively on GitHub you can use a more fine-grained personal access token: git remote set-url origin https://<token>@github.com/<user>/<repo>.git
Get origin with git remote -v
. You could also add one for no apparent reason.
Merge the main branch before pushing to it:
git merge origin/master
Or if you want to rewrite history which nobody else depends on, rebase:
git rebase origin/master
git push --force-with-lease
Conflicting files should be edited and staged as usual before committing the merge.
If git pull
(with git config pull.rebase true
to avoid littering your local branch with merge commits) complains, autostash:
$ git pull
error: cannot pull with rebase: You have unstaged changes.
error: please commit or stash them.
$ git pull --rebase --autostash
Updating 48a1590..660f95a
Created autostash: ac9d78e
Fast-forward
ide.html | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 ide.html
Applied autostash.
Auto-autostash with git config rebase.autoStash true
If you messed up and nobody is basing work on that yet, this fixes it:
git reset --hard LAST_GOOD_HASH
git push --force-with-lease --force-if-includes
--force-if-includes
ensures you're including the latest commit from remote. --force-with-lease
only ensures you've fetched that. If the remote is messed up, you can use git push --force
to overwrite it.
If your repo is FUBAR, rename it and clone again. You can compare file versions using commit hashes from git log --graph
: git diff OLD_HASH NEW_HASH [FILE]
To gatekeep commits, use .git\hooks\pre-commit
with your favorite linter, e.g.
#!/bin/sh
pylint *.py
or similar but more bloated versions generated by a Git hooks package manager such as the confusingly-named pre-commit.