[ | Date | | | 2023-05-27 18:15 -0400 | ] |
[ | Mod. | | | 2023-05-27 18:22 -0400 | ] |
[ | Current movie | | | I'm Gonna Git You Sucka | ] |
Here is an excerpt from my git-config
file:
[alias]
branch-name = rev-parse --abbrev-ref HEAD
ci = commit
co = checkout
comain = ! git checkout $(git-main-branch)
fmerge = merge --no-ff -
hedit = ! bash -c 'git rebase -i HEAD~$0'
heditm = ! bash -c 'git rebase -i $(git-main-branch)'
p = pull-request --draft
please = push --force-with-lease
pusho = ! bash -c 'git push --set-upstream origin $(git branch-name)'
rhardu = reset --hard @{upstream}
rpull = pull --rebase
rpulls = ! git stash save && git pull --rebase && git stash pop
slog = shortlog --no-merges --summary --numbered
sta = status
Not all of those aliases are great. Not all of them will be good for every person. Arguably, some Git operations are more easily performed using higher-level tools (perhaps Magit, tig, Sourcetree, Fork, IntelliJ): I encourage you to try some alternatives and find which you prefer.
Those rename existing, common Git commands, giving them shorter names.
Benefits: Reduce the amount of typing, serving the user’s sense of laziness. Document useful but semi-rarely used commands.
Drawbacks: Get you used to typing commands that will only work for you. It is best to use the longer version in external communication and in scripts, to avoid reliance on your personal alias settings being present.
Aliases:
ci
(“check in”): a shorter name for commit
.
co
: a shorter name for checkout
.
please
: push --force-with-lease
, which allows pushing a branch with a history that was locally modified, with more safeguards against accidental overwriting of concurrent changes than just push --force
.
slog
(“short log”): Print a list of the top committers for the current repository. I find this useful when getting to know a new repository, to get a sense of who contributed the most often. This can also be a way to locate the people most likely to be able to help with the repository’s code. The shortlog ignores merge commits in its count (--no-merges
), prints a single line per committer rather than a list of commits (--summary
), and sorts by decreasing count of commits rather than by developer name (--numbered
). Here is some anonymized sample output:
$ git slog
59 Julian Foo
16 Dave Bar
15 Bob Quux
6 Pete Baz
4 bobQuux
Note how the output has duplicates, because of contributors using different names. Identities can be merged by using a mailmap file (not explained here).
sta
: a shorter name for status
.
fmerge
(“feature merge”): Merges the previous branch into the current branch, introducing a merge commit. After moving from a feature branch to the main branch, this does much the same as GitHub’s “Merge pull request” button1.
rpull
(“rebase pull”): a shorter name for pull --rebase
; which requests updating the current branch with the remote state, rewriting history so that local, unpushed commits are additions to the work that was added to the remote.
rpulls
(“rebase pull with stash”): same as rpull
, but also works when there exist local, uncommitted changes, which plain push --rebase
does not support. This is not very robust, using stash
before and unstash after the pull operation, with no error recovery. If the pull --rebase
step fails, some manual unstashing can be needed.
hedit
, heditm
)This is a subject in its own right, and would best be demonstrated on an example repository.
hedit <commit-count>
(“history edit”)Running git hedit 4
, for example, will start editing the history of the last 4 commits (an “interactive rebase”). This opens a text editor list this many commits and their titles. Editing markers allows merging commits, and editing their messages. Reordering or removing lines allows reordering or deleting commits, respectively.
heditm
(“history edit main”)Starts the same history editing process as hedit
, but includes all commits leading to the main branch (using the git-main-branch
script as a dependency).
rhardu
)I think of this as “flipping tables” (╯°□°)╯︵ ┻━┻; “revert hard upstream”. This gets rid of any local changes, committed or not, making the current branch identical to its remote counterpart. I find this useful in two situations:
I broke my local history into a state I consider unfixable2; or
I meant to make changes to the branch, but was too slow and, after I pulled, someone else made functionally identical changes. rhardu
lets me continue from the point the other perseon reached.
comain
)Git repositories used to use master
as the default name for a repository’s main branch. More recent practice is to use main
as the name for the main branch. On top of that, some developers and project have different preferences and use other names for their main branch.
This alias checks out the repository’s main branch, without the developer having to remember what it is named. It relies on a command git-main-branch
existing:
#! /bin/bash
set -euo pipefail
get-main-branch-name() {
local ref
local branch
if ref=$(git rev-parse --abbrev-ref origin/HEAD 2>/dev/null); then
branch=${ref#origin/}
else
pat='main|master'
printf 1>&2 \
$'No `origin/HEAD\'; trying to match against `%s\'.\n' "$pat"
## Try to find a common name from one of the local branches
branch=$(git branch | grep --only-matching --max-count 1 \
--extended-regexp "\b($pat)\b")
fi
printf '%s\n' "$branch"
}
get-main-branch-name
pusho
)branch-name
This prints the name of the branch that is currently checked out. pusho
uses branch-name
as a dependency.
pusho
(push to origin)This pushes the current branch to and identically named upstream branch at origin. Useful when pushing a new branch for the first time. (Just git push
is insufficient with default Git settings, and I like to be explicit when creating a remote tracking branch).
p
)This alias is not to be passed to Git, but rather to GitHub’s hub tool (deprecated in favor of GitHub CLI), which also considers Git configuration files.
hub p
opens a GitHub pull request from the current branch, in Draft mode.
Quick links: