grokkingstuff Home Blog Projects Wiki Calculators About

Git

Why do I need version control?

As researchers, you (probably) want:

Version control systems allow you to keep the history of what you've developed for easy tracking if you actually develop the habit of using git. I've been burnt a few too many times by overwriting some program that works and wishing I had saved it before moving on to the next problem and messing everything up.

The basic git workflow is:

Letting git know who you are

Before continuing let’s configure git. You will have to do this once per computer you use git config --global:

git config --global user.name "Vishakh Pradeep Kumar"
git config --global user.email grokkingstuff@gmail.com
git config --global core.editor vim
git config color.ui auto

The --global option corresponds to a user-wide configuration. The configuration will be stored in a hidden repository in your home. You can also configure each git repository individually, by removing this option, or system-wide by replacing the --global option with --system. Usually, we just configure repositories user-wide.

You can check your configuration with:

git config --list

If you’ve configured git several times at different levels, you will probably see several entries twice or three times in the configuration list. The user-wide configuration overrides the system-wide configuration, and the local configuration overrides the user-wide configuration.

My .gitconfig file

[user]
    name = Vishakh Pradeep Kumar
    email = grokkingstuff@gmail.com
[color]
        ui = true
[core]
    pager = less -R
    compression = 6

[rerere]
    enabled = 1
[diff]
    mnemonicprefix = true
    tool = kdiff3
[merge]
    tool = kdiff3
[gui]
    editor = gvim
[guitool "edit"]
    cmd = gvim -f $FILENAME
    noconsole = yes
    needsfile = yes
[guitool "mergetool"]
    cmd = git mergetool -y -t kdiff3 $FILENAME
    noconsole = yes
    needsfile = yes
[push]
    default = matching
[mergetool]
    keepBackup = false
   # this is the most commonly used one, it turns out!
    fancy_log = log   --graph --boundary '--format=%Cblue%h%Creset %Cgreen%ar%Creset %Cblue%d%Creset %s' --all -19

    # this is so frequent for me...
    pom = push origin master
    # pushall = "!f() { git remote | map -p git push; }; f"
    pall = !git remote | map -p git push

    rl  = reflog show --date=relative

    ru  = remote update

Initializing repositories and configuring git

To initialize a new project, in the project directory, initialize the git repository with:

git init

The second way is:

git clone https://github.com/git-lectures/git-lecture-notes.git

This will clone the repository containing the documents of this tutorial.

Git

Rules

Josh, Glitter Lazygit seem neat. Think Like Git & What made you finally grok Git? are great reads.

Tools to look at:

Take the changes you've made and automagically identify which commits are safe to modify and which staged changes belong to each of those commits. Might go against the idea that a git's history should be unchangeable, but I guess this only modifies the last few things?

Great resources

Code

# set new git remote origin (https://stackoverflow.com/questions/16330404/how-to-remove-remote-origin-from-a-git-repository)
git remote set-url origin git://new.url.here
# Cleanup .git http://gcc.gnu.org/ml/gcc/2007-12/msg00165.html
git repack -a -d --depth=250 --window=250
# Reset to previous commit
git reset HEAD~
# Reset to commit
git reset <commit hash> --hard
# Checkout previous commit
git checkout HEAD~
# Create new branch
git checkout -b
# Revert changes to modified files (working changes)
git reset --hard
# New branch without git history & files
git checkout --orphan
# Show where git configs get defined
git config --show-origin -l
# Undo last commit but don't throw away changes
git reset --soft HEAD^
# List all git submodules
git submodule--helper list
# Pull from PR
git pull origin pull/<issue ID>/head
# List remote branches
git branch -a
# Delete branch
git branch -d
# Delete remote branch
git push origin --delete
# Force overwrite git repo. https://stackoverflow.com/questions/10510462/force-git-push-to-overwrite-remote-files
git push -f <remote> <branch>
# Reset to specific commit
git reset --hard <commit>
# Remove dir from git
git rm --cached -r <dir>
# Rename previous commit
git commit --amend
# Force push overwrite
git push --force origin master
# Hard reset a branch
git reset --hard <branch-name>
# Change remote. i.e. when making a fork of a clone to change upstream destination.
git remote rename origin upstream; git remote rename nikitavoloboev origin
# Change upstream to my name so it pushes there
git branch --set-upstream-to nikitavoloboev/master master
# Show changes between commits. Where f5352 and be73 are unique commit hashes.
git diff f5352 be73
# Update submodule
git submodule update
# Set PGP key for Git globally. <key> = fingerprint w/o spaces
git config --global user.signingkey <key>
# Clone git repo without history (much faster)
git clone [REPO] --depth 1
# Move your unstaged changes to a new branch (https://twitter.com/wesbos/status/1479129404500594691)
git switch -c <branch-name>
# Remove sensitive info committed (https://github.com/tj/git-extras/blob/master/Commands.md#git-obliterate)
git obliterate <>

Notes