4 ms·
An excerpt from my ~/.gitconfig, showing a related approach (piggy-backing on git-revise): [alias] # Revise into the commit that last changed File rf =
by chrismorgan 6y ago
An excerpt from my ~/.gitconfig, showing a related approach (piggy-backing on git-revise):
[alias]
# Revise into the commit that last changed File
rf = "!f() { if [ $# -eq 0 ]; then REV=\"$(git status --porcelain --untracked-files=no | sed '/^ /d;s/^.. //' | xargs -n1 git rev-list -1 HEAD --)\"; NUM_REVS=\"$(echo \"$REV\" | wc -l)\"; if [ $NUM_REVS -ne 1 ]; then >&2 echo Files in the index were not all last modified in the same commit; exit 1; fi; else REV=\"$(git rev-list -1 HEAD -- \"$1\")\"; shift; fi; git revise \"$REV\" \"$@\"; }; f"
(This alias is three times as long as my next longest aliases, which are ports of Mercurial’s id, tip, incoming and outgoing commands.)
This is more coarse-grained than the technique in this article, as it only goes down to the file level—because that was sufficient for me when I wrote the alias, and probably easier to implement. I’ve been vaguely contemplating trying git-autofixup and git-absorb for a while too, which include what are essentially more polished and powerful versions of my alias.
- taisalie 6y agoYou know that can go in $PATH/git-rf, right.
- chrismorgan 6y agoIf it grew much bigger I’d do that, but until it’s definitely too large, keeping all of this stuff in ~/.gitconfig is simpler, especially for sharing across heterogeneous machines.
- taisalie 6y agoYou can add a version-controlled directory to your PATH and put scripts in it. This can be in the same repository as your .gitconfig. So you can graduate aliases to scripts.
- chrismorgan 6y agoCopying a single file is regularly easier, and more flexible when working on machines not set up with your SSH keys or whatever.
- muxator 6y agohg incoming and hg outgoing are really useful. When I am in git, I use this version from https://github.com/sympy/sympy/wiki/Git-hg-rosetta-stone#setup https://github.com/sympy/sympy/wiki/Git-hg-rosetta-stone#set...: [alias] outgoing = !git fetch && git log FETCH_HEAD.. incoming = !git fetch && git log ..FETCH_HEAD Feature-wise, the mercurial command is way more powerful: https://www.mercurial-scm.org/doc/hg.1.html#incoming https://www.mercurial-scm.org/doc/hg.1.html#incoming
- chrismorgan 6y agoMy aliases for those two deals with remote-tracking branches (see git-rev-parse(1) for documentation of the @{upstream} part if you’re not familiar with it). Might as well provide a more full excerpt: # I almost always use glog rather than log. glog = log --graph # “Short log” slog = log --graph --oneline # `git id` = `git rev-list --max-count=1` with default refspec HEAD. id = "!f() { case \"x$1\" in x-*|x) refspec=HEAD;; *) refspec=\"$1\"; shift;; esac; git rev-list --max-count=1 \"$refspec\" \"$@\"; }; f" # `git tip` = `git log --max-count=1` with default refspec HEAD. tip = "!f() { case \"x$1\" in x-*|x) refspec=HEAD;; *) refspec=\"$1\"; shift;; esac; git log --max-count=1 \"$refspec\" \"$@\"; }; f" # `git out` = glog commits that exist locally but not on the upstream branch. No way to refer to different origins, sorry. out = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch@{upstream}..$branch\" \"$@\"; }; f" sout = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git slog \"$branch@{upstream}..$branch\" \"$@\"; }; f" # `git in` = glog commits that exist on the upstream branch (remember to fetch them first) but not locally. in = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch..$branch@{upstream}\" \"$@\"; }; f" sin = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git slog \"$branch..$branch@{upstream}\" \"$@\"; }; f"
- StavrosK 6y agoIs there one of these `@{}` tags that means "the point where this branch split off from master"? That'd be very useful, because that's usually the scope of my rebases.