3
votes

In my dotfiles I have the following function which works:

function undelete {
  git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"
}

…which I use like this:

$ undelete /path/to/deleted/file.txt

I'd like to scope this command since it's a git command.

How do I create a git alias so that I can use this git alias command?

$ git undelete /path/to/deleted/file.txt

Here are two, of my attempts which do not work:

git config --global alias.undelete "!f() { git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1; }; f"
git config --global alias.undelete "!sh -c 'git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1' -"
1
You're using doublequotes, so the shell does command and parameter and history expansion on the contents. Use single quotes so the shell passes the unexpanded contents to the git config command. Use '\'' to embed a singlequote in a singlequoted string.jthill
@jthill - Thank you! I'm curious, why didn't you post as an answer?Beau Smith
It's not exactly what comments are supposed to be for, but low-effort tossoffs aren't exactly what answers are for either, whether not I've got that I'm-sure-this-is-right feeling. Leaving unchecked short starter-material answers as comments so people like @torek who do a professionally thorough job of it every time can do that and get proper credit without worrying about stepping on anybody's toes seems like a workable compromise.jthill

1 Answers

3
votes

It is possible to do this with aliases (see jthill's comment):

git config --global alias.undelete '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1; }; f'
git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'

I recommend writing anything complicated as a shell script:

#! /bin/sh
#
# git-undelete: find path in recent history and extract
. git-sh-setup # see $(git --exec-path)/git-sh-setup

... more stuff here if/as appropriate ...
for path do
    rev=$(git rev-list -n 1 HEAD -- "$path") || exit 1
    git checkout ${rev}^ -- "$path" || exit 1
done

(the for loop is intended to make it allow multiple path names to "undelete").

Name the script git-undelete, put it in your $PATH (I put scripts in $HOME/scripts), and any time you run git undelete, Git will find your git-undelete script and run it (with $PATH modified to have git --exec-path up front, so that the . git-sh-setup works).