www.alxm.org

Git Notes

Contents

Repo Management#

Push to Multiple URLs#

Git remotes can be configured to push to multiple URLs, which is great for having backups and keeping things distributed. You can add extra addresses with git remote set-url --add --push origin git@host2:project.git or edit the project's .git/config directly:

1
2
3
4
5
[remote "origin"]
    url = git@host1:project.git
    pushurl = git@host1:project.git
    pushurl = git@host2:project.git
    pushurl = git@host3:project.git

Remotes should look something like this now:

1
2
3
4
5
$ git remote -v
origin  git@host1:project.git (fetch)
origin  git@host1:project.git (push)
origin  git@host2:project.git (push)
origin  git@host3:project.git (push)

Merge Two Separate Git Repos#

I create a new Git repo for every game jam project, but afterwards I merge it to a single archive repo that has all my past jam entries, preserving the original commit history of each.

Starting with the new game's repo at ~/newgamerepo, I first move everything from the project root to a subfolder:

1
2
3
4
$ cd ~/newgamerepo
$ mkdir newgame
$ git mv * newgame/
$ git commit -m "Move everything to the newgame subfolder."

Then I merge the game repo to the archive repo at ~/gamejams:

1
2
3
4
$ cd ~/gamejams
$ git remote add newgameremote ~/newgamerepo
$ git fetch newgameremote
$ git merge --allow-unrelated-histories newgameremote/master

The new game lands at ~/gamejams/newgame/. The --allow-unrelated-histories flag lets us merge Git histories with no common ancestors (two different repos).

Filter Changes of a Particular File by Keywords#

This lists commits that added or removed occurences of MyKeyword in a file:

1
git log -S "MyKeyword" -- path/to/file.txt

Repo Upkeep#

Remove Untracked Files#

To find all the files in the repo path that are not tracked by Git:

1
git ls-files --others

And to remove them:

1
git clean -dfx

Fix Issues Identified by git fsck#

I ran this command to validate the objects in an old Git repo that saw a lot of changes over the years, and it found some inconsistencies:

1
2
3
4
5
6
$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (6088/6088), done.
error: <object-id>: invalid sha1 pointer in resolve-undo
dangling commit 7cc415930bfcb31cd1c0501f54c2a452fb411156
Verifying commits in commit graph: 100% (694/694), done.

I ran the following to put the repo back into a good state and clear all the cruft:

1
2
3
4
git reflog expire --expire=now --all
git gc --aggressive --prune=now
rm .git/index
git reset

Now everything checks clean:

1
2
3
4
$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (907/907), done.
Verifying commits in commit graph: 100% (87/87), done.

Stop Tracking Remote Branch#

Suppose your local branch mybranch is set to track remote branch origin/mybranch, but then you delete the remote branch. The local branch still tracks the upstream you deleted:

1
2
3
$ git push origin :mybranch
$ git branch -vv
  mybranch caa5c94 [origin/mybranch: gone] Commit message

To clear the upstream:

1
2
3
$ git branch mybranch --unset-upstream
$ git branch -vv
  mybranch caa5c94 Commit message

Shell#

Show the Time and Git Branch on the Shell Prompt#

I set up my Bash prompt to show the current time, and if inside a Git repo path, to also show the name of the checked-out branch. The following goes at the end of ~/.bashrc, to override any previously set PS1 (the environment variable for the shell prompt's format string):

1
2
3
4
5
6
git_branch() {
    branch_name=$(git symbolic-ref --short HEAD 2>/dev/null)
    [ $? -eq 0 ] && echo "[$branch_name]"
}

export PS1='\t \u@\h \w$(git_branch) \$ '

The shell prompt should look something like this now:

1
2
3
18:44:06 alex@laptop ~ $ mkdir project && cd project
18:44:10 alex@laptop ~/project $ git init
18:44:20 alex@laptop ~/project[master] $

Convenient Single-Letter Aliases#

I keep a few short shell aliases in ~/.bashrc for the Git commands I use the most day to day. All of them are for read-only actions though, muscle memory can be dangerous when you're tired...

1
2
3
4
5
6
alias b="git branch -a -vv"
alias d="git diff"
alias ds="git diff --staged"
alias h="git show"
alias l="git log --graph --decorate=full --pretty=medium"
alias s="git status"

Colored Text in the Terminal#

Add to ~/.gitconfig:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[color]
    ui = true
[color "branch"]
    current = yellow reverse
    local = yellow bold
    remote = green bold
[color "diff"]
    meta = magenta bold
    frag = magenta bold
    old = red bold
    new = green bold
[color "status"]
    added = blue bold
    changed = green bold
    untracked = cyan bold