git

Remove a current tracking relationship

$ git branch --unset-upstream

source

Cryptographically sign all commits

commit.gpgsign

source

Revert a single file with uncommitted changes to HEAD

$ git checkout <filename>

Unstage a file

$ git reset HEAD <file>
$ git show --name-only [commit]

Undo commit and keep changes

$ git reset --soft @~1

source

Merge patches like you're a kernel maintainer

Kernel maintainers use the git am (apply-mail) command to get patches from a mailing list. GitHub has extended this command in hub to work with PR urls. This allows you to omit those nasty merge commits and update / prune files where needed.

$ hub am -3 <pull-request-url>

branching model

git-flow is probably the most popular branching technique out there. It's also shit. There are many caveats in it, and it doesn't use some use git primitives where it should. A successful branching model for simple projects is:

  • master is the truth of all merges
  • each feature gets their own branch on the contributor's fork
  • whenever a feature is done, it's pulled in
  • master gets a tag

It doesn't need to be complex to be efficient. If hotfixes need to be performed, master can be rebased on top of that. If features need to be removed, just request the commit range for certain tag to roll back. Tada!

Git hooks

Git hooks are a way of extending git with functionality whenever things happen. To some extent npm has a similar mechanism called npm scripts. Git hooks are just regular bash scripts that are triggered on actions. They live in .git/hooks, where the filename is the name of the hook. The following hooks are available:

applypatch-msg
pre-applypatch
post-applypatch
pre-commit
prepare-commit-msg
commit-msg
post-commit
pre-rebase
post-checkout
post-merge
pre-receive
update
post-receive
post-update
pre-auto-gc
post-rewrite
pre-push

Git hook scripts cannot be checked into version control. If you want to persist scripts between multiple users you must check them into the project itself and then symlink them back in, preferably in a bootstrap script. Be careful when running hard symlinks though, as they will overwrite any local files. Instead create an aggregator script that moves the original scripts and then imports the original + repo scripts back in.

Example functionality for git hooks includes: checking code style on commit, running extended tests on rebase to master, verify that no commit is performed while rebasing, semver is updated, etc.

git bisect

Find by binary search the change that introduced a bug.

$ git bisect start master f596075   # git bisect <bad> <good>
$ git bisect good                   # mark a commit as good
$ git bisect bad                    # mark a commit as bad
$ git bisect reset                  # exit git bisect
$ git bisect run ./test             # run an auto script after git bisect start

Manage main and fix commits

By running --fixup you can create fix commits for your main commit; this is a better alternative to continuously rebasing on top of your previous commit. With --autosquash the --fixup commits are automatically squashed into their relevant commit.

$ git commit --fixup <commit-sha>   # automatically marks your commit as a fix
                                    # of a previous commit
$ git rebase -i --autosquash        # automatically organize merging of these
                                    # fixup commits and associated normal
                                    # commits

To create a temporary commit message of which the value can be discarded during a rebase, prefix the message with fixup! <commit>.

To create a temporary commit message of which the value should be rolled back into the original commit, prefix the message with squash! <commit>.

A best practice is to create a new empty commit, create a TODO list of the scope of the commits and roll back all relevant commits into this commit using squash! and fixup!.

Unstage directory

$ git rm --cached -r dir

Unstage file

$ git reset HEAD <file>

Change remote to SSH

$ git remote set-url origin [email protected]:<username>/<repo>.git

Rebase the first 2 commits in git

The root commit is protected by default, the --root flag enables modification:

$ git rebase -i --root

link

Git blame

Sometimes you want to know who wrote a certain piece of code. git blame to the rescue!

$ git blame <filename>                    # git blame a complete file
$ git blame -L <start>,<end> <filename>   # git blame between certain lines

Safer force push

--force is dangerous as it blindly overwrites; --force-with-lease will check if the ref hasn't been modified before force pushing.

$ git push --force-with-lease

Git get theirs / pull --force

$ git reset --hard origin

Show staged files changes

$ git diff --cached

Git stash pop conflicts

When git stash pop fails, the stash is not dropped, but changes are floating. You can safely git reset --hard on top of this to unapply the stash since it's kept in the stash list still.

Safe git stash

  • git stash apply - apply a git stash without destroying the stash

Git fsck

Inspect individual objects in the DB.

Git tags

git tag v1.0.0                   # create tag called 'v1.0.0'
git push --delete origin <tag>   # delete remote tag
git tag -d <tag>                 # delete local tag

Git submodules

$ git submodules add <repo-name>
$ git submodule update --recursive

Remote branches

$ git remote -vv                # display remote branches
$ git branch --unset-upstream   # remove tracking relationship with upstream
$ git push -u origin head       # push to current branchname on origin remote

Show root commit

$ tag_commit="$(git rev-list --max-parents=0 HEAD)"

git branch status

$ git branch -vv

create a new empty branch

Create a new branch that's detached from the history from the branch that it's being forked off.

$ git checkout --orphan <branchname>

stash files that haven't been checked in yet

$ git stash save -u

save stash with name

$ git stash save "<name>"

Git worktree

Check out a branch into a directory

$ git worktree add <path> <branch>

Force pull

From SO:

$ git fetch --all
$ git reset --hard origin/master

Get current git branch

$ git rev-parse --abbrev-ref HEAD

Fix refs errors

In case of remote: fatal error in commit_refs, run git gc

$ git gc

See Also

results matching ""

    No results matching ""