Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expansion of alias failed; not a git command

Tags:

git

I must be missing something obvious... but Git aliases are not working at all. Help me please!

$ git config --global alias.v version
$ git config --global --list
alias.v=version
$ git config --global alias.v
version
$ git v
Expansion of alias 'v' failed; 'version' is not a git command
$ git version
git version 2.9.0
$ cat ~/.gitconfig
[alias]
        v = version

Update 1

As per @torek's suggestion, I tested the same thing with log, and it also doesn't work:

$ git config --global alias.l log
$ git config --global --list
alias.v=version
alias.l=log
$ git config --global alias.l
log
$ git l
Expansion of alias 'l' failed; 'log' is not a git command
$ cat ~/.gitconfig
[alias]
        v = version
        l = log

Update 2: Solved

The problem was that git --exec-path was somehow set to an incorrect directory. In the end, I built and installed from source and now everything works as expected. Thanks to everyone who helped.

like image 598
Will Hains Avatar asked Dec 06 '22 08:12

Will Hains


1 Answers

Use a command other than version. Try aliasing l to log, for instance. (Or, as VonC notes, upgrade—it actually does work in modern Git. The alias handling seems to have been rewritten between 2.17.3 and 2.18.0.)

Why does l = log work, and yet v = version not?

This is a little tricky!

Most Git commands are—and at one point, all Git commands were—separate programs that are installed separately into a directory (or folder, if you prefer the term) full of "Git commands you can run". For instance, git log is actually implemented by a command spelled git-log, which is installed in a special directory / folder.

This directory / folder is not one you normally run commands from, though.

Back in the distant past, these Git commands—git-log, git-commit, git-add, git-diff, and so on—were all installed directly, and you ran them directly, by typing in git-something. This worked OK with bash's autocompletion, in that you could type git-comTAB to get the commit command, or git-chTAB to get the checkout command. But over time, the number of Git commands grew (git-cherry and git-cherry-pick), and grew, and grew; and eventually even typing in the full command git-add wasn't enough because there's also git-add--interactive for instance, so the TAB completion basically completely stopped working.

A decision was made: Git wasn't going to stop coming with 57 different commands—actually, it's over 150 now—but instead, all these various implementation commands would be stuffed away into a place where they would not be all up in your face all the time. A single front end command, spelled git, would let you type in the command as an argument to the front-end git command: git com, then TAB: bash now has a list of allowed completions, and will only pick commit since that's the only com that you would use, not the git-commit-tree or git-commit-graph back end programs that only scripts regularly use.

So: the front end git command knows how to find and run all the various back end implementations. By convention, most of them are in the git-core directory: run

git --exec-path

and the front end prints out the name of the place where all the back-end programs actually live. (You can look in there, and even run them out of there directly if you like, although these days the front end git command now sets up information that the back end commands may want.)

But what about git version? Well, now that you know that Git commands actually live in the git-core folder, wherever that may be on your system, I suggest you look in there. Where is the git-version program? You will find git-checkout in there, and git-log, and git-commit, and git-diff and many others, but you won't find a git-version. There isn't one.

The version command is built directly in to the front end. The aliases only work when invoking a back end command. So there is—or was, anyway—no way to alias version. (At some point, obviously post 2.9 and pre 2.24, the alias handling code was smartened up to check the front-end built-ins as well.)

There's one more important thing to know

The front end git command does know about some common back end commands, but it doesn't have a complete list of back end commands. Instead, when you type in git asdf or git rumplestiltskin or git helloworld—none of which are actual Git commands—it just sets things up as usual and then attempts to run git-asdf or git-rumplestiltskin or git-helloworld, while telling the system to look in the git-core directory. It doesn't tell the system not to look in other directories.

This means you can write your own Git commands. If you want a git asdf, you can write your own git-asdf program, and put it anywhere so that running git-asdf succeeds. You can now run it using git asdf.

Why, you might wonder, would you want to do this? If you install git-asdf in your own personal bin or scripts folder, you can just run git-asdf. And indeed, you can do that. But when you have the front end run it, you're run with special Git setup information provided. This gives you the ability to write your program as an sh (or bash) script and get direct access to various Git helpers. The main helper is called git-sh-setup and you invoke it by "sourcing" it, with . (POSIX) or source (bash):

#! /bin/sh
. git-sh-setup

This adds shell functions die and say and git_pager and require_clean_work_tree and more. If you set the shell variable OPTIONS_SPEC before sourcing git-sh-setup, it will parse arguments for you. Look at the script—it's right there in the git-core directory—to see how to use it.

(Note that, like all things Git, it has grown over time. It has more functions now than it did in the days of Git 1.7, for instance. If you want something that backports to older versions of Git, clone the Git repository for Git, pick a compatibility level, and git checkout the old one to see what you can rely on.)

like image 142
torek Avatar answered Feb 28 '23 09:02

torek