Quick references for basic tasks with git.

Installation & Tools

Rules to be more effective

  • Do commit early and often.[ref]
  • Do make useful commit messages.
  • Create a new branch for every new feature.
  • Use pull requests to merge code to master.[ref]
  • For temporary branches, name them starting with _.

Settings on local machine

# SET GLOBAL INFO
git config --global user.name "Anh-Thi DINH"
git config --global user.email "[email protected]"
# IF: `Could not resolve host: github.com`
git config --global --unset http.proxy 
git config --global --unset https.proxy
# SAVE GITHUB AS DEFAULT
# (don't need to log in again every time we use)
git config credential.helper store
git pull
# FORMATTING DISPLAY
git config color.ui true # add colors to the results
git config format.pretty oneline # disply only one line of each commit

Check the status

# CHECK STATUS
git status
git status -s # modified files
# Get remote list
git remote -v
# WITH COLORS
git log --oneline --graph --color --all --decorate
# --graph: draw text-based branches
# --decorate: display names and tags

Check some commit:

git log -- <file> # check commits containing <file>
git log --prep='abc' # look for commits containing "abc" in their name
git log <from>..<to> # display commints from <from> to <to> (commit's id, branch's name,...) 

Check current HEAD

git log -1
# something likes HEAD -> <branch-name>

Check the change of some file,

git diff file_name.abc 

Repositories

# CREATE REPO
git init <repo-name>
# CLONE REPO (using https or ssh)
git clone <repo-link>

Git GUI

git gui
gitk

Staged & Commits & Push & Pull

Staged

# ADD MODIFICATION (1 FILE)
git add * # add all the changes
git add <file-name> # only add the <file-name> to the staged
# UNSTAGE A FILE
git reset HEAD <file>
# UNSTAGED EVERYTHING
git reset

Commit & Push

# MAKE COMMIT (FROM STAGED)
git commit -m '<comment-for-this-commit>'
git commit -a # commit any files
# PUSH TO REMOTE
git push origin <branch-name> # push only <branch-name>
git push --all origin # push all branches
# CHECK & TEST A COMMIT
git checkout <commit-id>
# after testing
git checkout <current-branch>

Pull

# LIST ALL REMOTE REPOS
git remote -v
# UPDATE REMOTE -> LOCAL
git pull origin <branch-on-remote>
# COPY A COPY FROM REMOTE
git fetch origin <branch-on-remote>
# compare current branch to this copy
git diff --stat FETCH_HEAD

Branches

Create

# CREATE A BRANCH
git branch <branch-name>
# CREATE AND MOVE TO NEW BRANCH
# This one is based on the current `HEAD` (git log -1).
git checkout -b <new-branch>
# new branch based on another one
git checkout -b <new-branch> <existing-branch>

Two branches

# CHANGE TO ANOTHER BRANCH
git checkout <branch-name>
# LIST ALL LOCAL BRANCHES
git branch
# LIST ALL LOCAL + REMOTE
git branch -a
# UPDATE ALL REMOTE BRANCHES TO LOCAL
# (there may be deleted branches on remote)
git remote update origin --prune
# COMPARE 2 BRANCHES
git diff <source-branch> <compared-branch>
# LOCAL <-> REMOTE BRANCHES
git branch -vv
# CORRESPONDING LOCAL BRANCH <-> REMOTE
git branch --set-upstream-to=origin/<remote_branch> <local_branch>

Delete

# DEL A LOCAL BRANCH
git branch -d <branch-name>
git branch -D <branch> # force to delete
# DEL A REMOTE BRANCH
git push origin :<branch-name>

Merge

# MERGE <branch> TO CURRENT
git merge <branch>
# MERGE <sub-branch> TO master + REPLACE master
git checkout <sub-branch>
git merge -s ours master
git checkout master
git merge <sub-branch>
# MERGE `/link/to/abc.xyz` FROM `<branch-1>` TO `<branch-2>` (can be `master`)
git checkout branch-2
git checkout branch-1 /link/to/abc.xyz
# MERGE ONLY SOME FOLDER
git checkout <branch>
git checkout <from-branch> folder1\ folder2\
# MERGE commit from ONE BRANCH to CURRENT
git cherry-pick <commit hash>
# KEEP FILES/FOLDERS FROM MERGE
# add line to .gitattributes
echo 'file_name.txt merge=ours' >> .gitattributes 

Conflict

If there are changes from both local and remote, there will be conflicts! Something likes that,

<<<<<< HEAD
changes on local
======
changes from remote
>>>>>> template/notetheme2

If you use Visual Studio Code, there is a small toolbar above each conflict and you can choose which one you prefer to keep!

Prefer one of them?

# keep remote changes
git pull -X theirs <remote-repo>
# keep local changes
git pull -X ours <remote-repo>

Keep both? Using Visual Studio Code or,

# add below line to .gitattributes (on branch being merged)
echo "*.whatever merge=union" .gitattributes
# on windows, remove `""`

Already in conflicted state?

git checkout --theirs path/to/file # remote
git checkout --ours path/to/file # local
# Abort the conflicts
# (go back to before merging)
git merge --abort

Exclude from merging

Exclude some files from merge (keep ours),

# ONLY FOR FILES
# add below line to .gitattributes (on branch being merged)
echo "file.ext merge=ours" .gitattributes
# on windows, remove `""`

Exclude some folders (we cannot use git in this case):

  1. If you delete these folders after merging, just commit and later merges will ignore them.
  2. If you meet a conflict, add the folder’s name in a file called reset_folders.sh,
    #!/bin/sh
    echo 'Reset some only-this-branch folders after merging.'
    git reset folder_1, folder_2 
    git checkout .
    git add .
    git commit -m "update from merge (keep local in some folders)"
    

    Each time,

    git merge <from-branch> && sh reset_folders.sh
    

Rename

# CURRENT BRANCH
git branch -m <newname>
git branch -M <newname> # if there are only capitalization changes 
# CURRENT IS ANOTHER BRANCH
git branch -m <oldname> <newname>
# RENAME REMOTE BRANCH (delete old + push new)
# (rename local branch first)
git push origin :<oldname> <newname>
# reset the upstream branch for the new-name local branch
git checkout <newname>
git push origin -u <newname>

Others

Add a description (using Vim editor):

git branch --edit-description

In the case you wanna exit Vim, press ESC then type :q to quit or :wq to write and quit.

Discard the changes

# DISCARD CHANGES ON CURRENT DIR
git checkout -- . # for all changes
git checkout -- <file-name> # for a specific file (go back the last commit of this file)
# DISCARD ALL LOCAL CHANGES
git reset --hard

In the case you want to discard the changes but want to make a save before moving to another branch to test. You can use below line.

git stash

If you wanna get back to the place you saved (and remove it from the stashed list), just go back to the branch you make the save and use

git stash pop

Restore

# RESTORE FROM LAST COMMIT
git checkout -- <file>
# DISCARD ALL CHANGES ON LOCAL + GET FROM REMOTE
git fetch origin
git reset --hard origin/master
# EREASE ALL COMMITS + BACK TO <commit-id>
git reset --hard <commit-id>

Alias

Normally, we use git branch. If we wanna use git br instead, we use an alias:

git config alias.br branch

Gitlab: Clone a private repo to local

  1. Open and copy key in C:\Users\dinha\.ssh\id_rsa.pub
  2. Go to Gitlab > Settings > SSH Keys > paste a copied key and name it.
  3. Clone again the repo and it shoule be working!

Github

Info

  • Commits to a fork don’t appear in your contributions graph.
  • Commits to a generated from template can appear in your contributions graph.

Repo template

I wanna make a theme notetheme2 based on dinhanhthi.com.

  1. Make dinhanhthi.com be a template (Go to Settings)
  2. Create a new repo based on this template.
  3. Create a new branch notetheme2 on dinhanhthi.com. Make changes on this branch.
  4. Everything we have a “theme change” on dinhanhthi.com/master, merge it to branch dinhanhthi.com/notetheme2.
  5. If there are files (only for files) in dinhanhthi.com/notetheme2 you wanna keep, add below line to .gitattributes (under branch dinhanhthi.com/notetheme2) before performing the merge,
    # add line to .gitattributes
    echo 'file_name.txt merge=ours' >> .gitattributes 
    # on windows, remove `''`
    
  6. If there are folders (or files) in dinhanhthi.com/notetheme2 you don’t wanna keep (from /master), just delete them and make a new commit. From this time, later merges will ignore them.
  7. If there are folders in /notethem2 you wanna keep the current state (instead of merging from master), create a script reset_folders.sh
    #!/bin/sh
    # used for branch notetheme2 only
    echo 'Reset some only-this-branch folders after merging.'
    git reset folder_1 folder_2
    git checkout .
    git add .
    git commit -m "update from master"
    

    Each time you run the merge, run

    git merge master && sh reset_folders.sh
    
  8. Update changes from dinhanhthi.com/notetheme2 to repo notetheme2[ref] .
    # add dinhanhthi.com as a remote
    git remote add template [URL of the template repo]
    
    # update the changes
    git fetch --all
    
    # update from template's branch
    git merge template/notetheme2
    
  9. If there is an error fatal: refusing to merge unrelated histories, try to add --allow-unrelated-histories. There must be conflict.
    # keep remotes
    git merge -X theirs template/notetheme2 --allow-unrelated-histories
    # keep local
    git merge -X ours template/notetheme2 --allow-unrelated-histories
    

Errors

  • fatal: Authentication failed for: It’s because you enabled two-factor authentication in your Github account.
    1. Generate a new token: click here.
    2. Copy that token and use it as a new password.