Clone git repo
git clone https://github.com/user/project.git
git clone ssh://git@github.com/user/project.git
gh repo clone user/project
GitHub how to
Get started with GitHub
Create new repo (add existing project to Git)
# Create also remote repository, i.e. create repo on GitHub
git init -b main # previously master, init.defaultBranch
echo "New project" > README.md
git add . # or: git commit -a
git commit -a -m "Initial commit"
git remote add origin https://github.com/user/project.git
git remote add origin git@github.com:username/project.git
git remote -v # verify
git push -u origin main # previously master
# configure default name of main branch:
git config --global init.defaultBranch main
see also:
Create new repo in GitHub (how to)
Add existing project to GitHub
Pull
git pull # update (fetch) from remote tracking upstream, merge into current branch
git pull origin # update from origin
git pull origin branch1 # update from origin, merge remote branch1 into current branch
# or:
git fetch origin
git merge origin/branch1
git pull –-all # fetch all remotes
Show branches
# local:
git branch -l
# remotes:
git branch -r
# all:
git branch -a # remotes prefixed with "remotes/"
# current:
git branch --show-current
# branch parent:
git parent
# git parent alias in Windows Cmd:
git config --global alias.parent2 "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//' #"
src: stackoverflow
# git parent alias in Linux or Windows Git Bash:
git config --global alias.parent2 "!""git show-branch | grep '*' | grep -v \"\$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//' #"
src: stackoverflow
# creates following alias in ~/.gitconfig :
[alias]
parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"
Switch to another git branch
# switch to and reset (-B) local branch or create new local :
git checkout -B branch1 origin/branch1
# switch to existing local branch:
git checkout branch1
# since git 2.23.0:
git switch branch1 origin/branch1
Clone/Create branch and switch into it
# create (-b) new branch1 from origin/master^0, checkout (optionally: --track, --no-track)
git checkout -b branch1 origin/master^0 --
More at StackOverflow
Push new local branch to remote
git push -u origin HEAD
git push -u origin refs/heads/branch1:branch1
Merge branch1 to master
git checkout origin/master
git merge origin/branch1
git push
git push origin HEAD
git push origin refs/heads/master:master
Merge remote branch1 into current branch
git pull origin branch1
git push
Merge Squash
git checkout origin/master
git merge --squash origin/branch1
git push
Merge without merge commit / avoid merge commit
git checkout origin/master
git merge --ff-only origin/branch1
git push
src: Q: stackoverflow
Merge using Patch
git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .
src: stackoverflow
Merge conflicts - resolve conflicts
# resolve conflicts:
vim file1.txt # resolve conflicts
git mergetool # resolve conflicts
# add (stage) resolved changes to index:
git add -A -f -- file1.txt # add (-A now equiv to ., including removal)
git add -u # add all modified (previously added)
# commit resolved changes:
git commit -a -m "commit message" # add and commit
git commit -F C:\git\project1\.git\MERGE_MSG --
Merge - resolve conflicts helpers
git status
git log --merges # print only merge commits
git diff
git checkout
git merge --abort
git reset
git mergetool # uses merge tool to resolve merge conflicts
git am --show-current-patch # see failed patch (from merge)
see: atlassian - merge conflicts
Merging strategies
ours
theirs
patience
octopus (?)
diff-algorithm
see: atlassian - merge strategy
Rebase
git checkout origin/branch1
git rebase origin/master
git add fixed_file.txt
git commit -m "fixed conflict"
git rebase --continue # skip, abort
git push --force
Rebase pull
git pull --rebase
Config:
git config branch.autoSetupRebase always
git config --global pull.rebase true
git config --global pull.rebase preserve # set up Git to automatically rebase upon pull
src: stackoverflow
# Change parent branch:
git rebase --onto origin/newBase
# Interactive rebase (squash, drop, ...)
git rebase --interactive origin/master
git rebase -i origin/master
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
See more about Rebase
The Golden Rule of Rebasing
Never rebase public branches
# Rebase public branch – if ever:
git --fork-point
Undo git rebase
git reset --hard ORIG_HEAD # rebase saves start point
git reflog # find head commit before rebase
git reset --hard "HEAD@{2}"# reset to commit before rebase
# proper config:
git config core.logallrefupdates=true
Push
git push # Push to tracked/upstream/remote
git push origin branch1 # Push to branch1
git push -u origin branch1 # Push to branch1 and set upstream
git push -u origin local1:remote1 # push local1 to remote1 and set-upstream
See Push default
Push force
git push --force-with-lease
git push --force-with-lease origin X
src: stackoverflow
src: stackoverflow
Push tags
git push --tags # tags are not pushed automatically
Push all
git push --all # all branches
Delete branch
# Delete local:
git branch -d branch1
# Force delete local
git branch -D branch1
# Delete remote:
git push --delete origin/branch1
# SOLVED: fatal: --delete doesn't make sense without any refs
git push origin :branch1 # actually deletes branch1
Rename branch
git branch -m branch1 # rename current branch to branch1
Prune
# Delete local branches without remotes
git remote prune origin --dry-run # prunes tracking branches not on the remote
git fetch -p
git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done
Note: see differences between differences between git remote prune, git prune, git fetch --prune, etc
Git tag
# Tags are ref's pointing to git history. Types:
# lightweight tags (absence of the -a, -s, -m),
# annotated tags
# Lightweight tag (absence of the -a, -s, -m)
# Create a new tag checksum and store it in the .git/ of project's repo
git tag v1.4
# Annotated Tag
# full objects in the Git database (store the tagger name, email, and date)
git tag -a v1.4
# Add (commit-like) tag message:
git tag -a v1.4 -m "my version 1.4"
# List tags
git tag
git tag -l *-rc*
# Tag old commit
git log --pretty=oneline
git tag -a v1.2 commit-id
# fatal: tag 'v0.4' already exists => force
git tag -a --force v1.4 commit-id
# Push tag:
git push origin v1.4
# Checkout tag:
git checkout v1.4
# Delete tag:
git tag -d v1
# Prune tags:
git fetch --prune-tags
src: atlassian.com
Reset branch (move back in history)
# reset your branch to master and destroy changes:
git reset --hard origin/master
# reset your branch to master and keep changes as commited:
git reset --soft origin/master
# reset your branch to master and mixed (not added to index):
git reset --mixed origin/master
Commit References (move back in history)
HEAD~ and HEAD^
~ most of the time
^ on merge commits
*
Tilde ~ is almost linear in appearance and wants to go backward in a straight line
Caret ^ suggests an interesting segment of a tree or a fork in the road
*
Order of Parent Commits
Show 89e4fcb0dd’s immediate parents in sequence:
git rev-parse 89e4fcb0dd^1 89e4fcb0dd^2 89e4fcb0dd^3
src: good article: stackoverflow
Cherry pick
# Syntax:
git cherry-pick commit-sha
# i.e.: you want to get f into Main:
a - b - c - d Main
\
e - f - g Feature
git checkout main
git cherry-pick f
Options
git cherry-pick -x f # generate standard commit message – keep track of origin of commit
https://git-scm.com/docs/git-cherry-pick#Documentation/git-cherry-pick.txt--x
git cherry-pick --edit f # you can edit commit message
git cherry-pick --no-commit f # do cherry pick but do not commit and keep changes in working directory
git cherry-pick --signoff f # add signoff signature to end of cherry-pick commit message
git cherry-pick --abort --continue –quit # when solving conflicts
Copy notes attached to cherry pick:
git notes copy <from> <to>
https://stackoverflow.com/questions/9339429/what-does-cherry-picking-a-commit-with-git-mean
example: https://stackoverflow.com/a/30218784
*
see also: atlassian: merge-strategy
Revert file
# remove untracked including ignored:
git clean -fd # remove untracked directories and untracked files
git clean -fX # remove only ignored files
git clean -fx # remove directories, ignored and non-ignored untracked files (include build target)
src: stackoverflow
answer: stackoverflow
-n, --dry-run # dry run
git clean -i # interactive
git add --all && git reset --hard HEAD
src: https://stackoverflow.com/a/37614185
# undo/revert local changes:
git reset --hard
git stash
git reset HEAD file1.txt # unstage to current commit
git checkout -- file1.txt
git checkout HEAD -- file1.txt
# revert (remove) uncommited file:
git rm --cached -f -- file1.txt
git reset file1.txt
See more at Revert all local changes
Stash
# simple:
git stash
git stash -u # include ignored and untracked
git stash pop
# name stash:
git stash save "my stash name"
# list
git stash list
# apply and keep
git stash apply stash@{0} # apply and keep
git stash pop # apply/pop and drop
# branch from stash
git stash branch branch1 stash@{2}
# view details
git stash show
# delete
git stash drop stash@{1}
# delete all
git stash clear
Git log
git log --oneline --decorate
git log --graph --oneline --decorate
git log --pretty=format:"%cn committed %h on %cd"
git log -3 # 3 lines
git log main..feature
git log --no-merges
git log -–merges
src: https://www.atlassian.com/git/tutorials/git-log
# Pretty format
git log --all --decorate --oneline -–graph # "A Dog"
git config --global alias.adog "log --all --decorate --oneline --graph"
Ref log
# Show git commands history:
git reflog
git reflog --relative-date
git reflog --all
git reflog show
See more Many undo possibilities
See on Atlassian
Push default
git config --global push.default matching # old default behavior
git config --global push.default simple # new default behavior
See default git push
See push -u
Upstream config
# snippet of git config – refs remotes upstreams :
git config --local -–list | grep '^remote'
# remote and refspec def :
remote.origin.url=https://github.com/username/project.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
# branch master :
git config --list | grep "^branch"
branch.master.remote=origin
branch.master.merge=refs/heads/master
src: stackoverflow.com
Set branch upstream
# If you create new branch:
git checkout -b branch1 origin/branch1
git push -u origin HEAD
git branch -u origin/branch1 branch1
git push origin refs/heads/branch1:branch1 --set-upstream
git push origin refs/heads/branch1:branch1 -u
# updates git project config as :
branch.branch1.remote
branch.branch1.merge
# Config branch:
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
Remote origin (add show update)
git remote add origin https://github.com/user/project.git
git remote show origin
git remote update
# Set remote URL (https or ssh)
git remote set-url origin https://github.com/username/project.git
git remote set-url origin git@github.com/username/project.git
# Check remote URLs
git remote -v
origin https://github.com/username/project.git (fetch)
origin https://github.com/username/project.git (push)
# Show Git remote URL
git config --get remote.origin.url
Parent branch - merge base
git merge-base branch2 branch3
git merge-base origin/main branch1
git reset $(git merge-base master $(git branch --show-current))
git show --summary `git merge-base foo master` # when was branch created
git log --first-parent
Git commands workflow
HEAD working tree, index, staging area:
Workspace is the directory tree of (source) files that you see and edit.
Index is a single, large, binary file in <baseOfRepo>/.git/index, which lists all files in the current branch, their sha1 checksums, time stamps and the file name -- it is not another directory with a copy of files in it.
Local repository is a hidden directory (.git) including an objects directory containing all versions of every file in the repo (local branches and copies of remote branches) as a compressed "blob" file.
src: stackoverflow
Git config - initial setup
https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup
*
git config --global user.name 'Jon Doe'
git config --global user.email 'jon.doe@github.com'
git config --global core.editor emacs
git config --global core.editor vim
git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
git config --global init.defaultBranch main
*
git config -l
git config --list [--local | --global | --system]
Git config - which config
git config --show-origin --list # show config origin
*
Git config - files
# source:
[path]/etc/gitconfig # system
~/.gitconfig or ~/.config/git/config # global
.git/config # repository
Git alias
git config --global alias.alias "!""git config -l | grep ^alias\\."
git config --global alias.configure "!""vi ~/.gitconfig"
src:
CRLF:
git config core.autocrlf true
git config core.autocrlf false
git config core.autocrlf input
# src: stackoverflow.com
Different Git configs
git config --list # local: /.git/config - repo-specific
git config --global --list # global: /.gitconfig - user-specific
git config --system --list # system: $(prefix)/etc/gitconfig - system-wide
git config --global --edit # edit
Global proxy settings
git config --global http.proxy myproxy.com:8080
Global SSL verify
git config --global http.sslVerify "false"
git config --global --unset http.sslVerify
Project specific SSL verify
cd C:\git\my-project
git config http.sslVerify "false"
:: git config --unset http.sslVerify
Git template dir:
# ~/.config/git/config or ~/.gitconfig
[init]
templateDir = ~/.config/git/template/
Relative Refs
# display the grandparent of HEAD:
git show HEAD~2
merge commits => more complicated
merge commints => more parents => more paths to follow
i.e. 3-way merge:
1. parent == main branch you merged into
2. parent == branch mentioned in git merge branchName
~ = follow first parent of merge commit
^ = follow different parent
i.e.: if HEAD is merge commit, display second parent of HEAD by:
git show HEAD^2
Combine into:
git show HEAD^2^1
it is: grandparent of HEAD (if merge commit) which is on the second parent.
Examples:
# Only list commits that are parent of the second parent of a merge commit
git log HEAD^2
# Remove the last 3 commits from the current branch
git reset HEAD~3
# Interactively rebase the last 3 commits on the current branch
git rebase -i HEAD~3
# get back before you ran git reset
git checkout HEAD@{1}
src: atlassian.com
SSH Keys
ssh-keygen -t rsa -b 4096 -C 'username@github.com'
details: https://stackoverflow.com/a/37075506
files: https://en.wikipedia.org/wiki/Ssh-keygen
Linux SSH Keys registration
cat > ~/.ssh/config <<EOF
Host vs-ssh.visualstudio.com
IdentityFile ~/.ssh/id_rsa
EOF
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Sources
Cheat sheets
Atlassian git cheat sheet page
Atlassian git advanced – crossroad
Rebase reset revert log hooks refs reflog