- 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 johndoe@example.com
or if he's a GitHub user, so you see his icon: johndoe@users.noreply.github.com
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.
You can ignore your editor's config files globally with for example git config --global core.excludesFile '~/.gitignore' and nano ~/.gitignore .vscode/ Ctrl+S, Ctrl+X.
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 add -u .` to ignore untracked files.
$ 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_NAMEThat -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 (add --dry-run to preview):
git fetch --prune
View local branches that are gone on remote:
git branch -vv | grep gone]
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 git@gitlab.company.com:project/components/subproject.git
git branch -u origin/TICKET TICKETAlternatively 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/masterOr 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, reset to a good state (with --hard to reset ALL modified files; without to simply undo the commit(s) to split or squash them for example, which is easier using git rebase -i HEAD~2 if you want to keep/amend the last 2 commit messages):
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.
pr-fix.sh:
git fetch --all && git rebase -i upstream/master && git push --force-with-lease originIf people are basing work on the latest commit, use git revert BAD_HASH to make a new commit undoing the changes of the old one.
git reflog or git log -g (garbage, not to be confused with git log -G"foo|bar" --full-diff -p diff reGex search) can show you deleted commits.
If git randomly (seems to happen while rebasing) complains about changing CRLF to LF and vice versa like in this project:
core.autocrlf = falsewithcore.eoldefault""being native CRLF on Windows turns all text file line endings to CRLF on checkout, reset, and commit!core.autocrlf = trueturns line endings to LF on commit.core.autocrlf = inputturns line endings to LF on checkout and commit. Your editor like Visual Studio Code which fails to display line endings even when set to show whitespace and control characters might also convert line endings.
A file with mixed line endings would be reported by the core.safecrlf mechanism.
core.safecrlf = trueaborts line ending changes.core.safecrlf = warnonly warns. Useful if using raw HTML templates for example.
Simplest way to get rid of line end issues is to commit and drop those changes.
If it still messes up, nuking git's cache should help: git rm --cached -r .
If you pushed and deleted paths that don't belong in Git, and would like them not in your history either, rewrite history in a fresh clone with git filter-repo, which normally only keeps the paths you supply, hence the invert:
python -m pip install git-filter-repo
git filter-repo --path-glob "*.exe" --invert-paths
git remote add origin $ORIGINAL_CLONE_URL
git push --force --prune origin --branches
git push --force --prune origin --tags
# That writes refs/heads/* and refs/tags/*
# To make origin an exact copy, potentially removing managed namespaces like refs/pull/* PR metadata,
# releases, workflows, etc.: git push --force --mirror origin
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 for example your favorite linter:
#!/bin/sh
pylint *.pyor similar but more bloated versions generated by a Git hooks package manager such as the confusingly-named pre-commit.