loading...
Cover image for The case against aliases

The case against aliases

moopet profile image Ben Sinclair ・3 min read

A quick glance at the timeline here will show you that shell aliases are a popular topic. Still popular but to a lesser extent are shell functions, git aliases and wrapper scripts.

There's nothing wrong with liking aliases!

But I think that, as with everything, you should understand what you're doing before you do it.

Copypasta

When you use someone else's aliases it's typically by pasting in a whole bunch or sourcing an entire file of them. Did you read everything through and understand it? Is there something malicious in there? Is there something not-so-malicious but put in there for a joke?

Cargo cults

Some aliases you find shared on the interwebs are highly opinionated. For a trivial example, should mkdir shadow command mkdir -p? Do you know why you're choosing to do that, or is it just someone else's preference?

Recursion

What happens if one alias calls another, which calls another (or itself)?
You can often get around this by explicitly specifying an alias uses command if appropriate or by making sure the script providing your aliases is nicely ordered and commented.

I'll bet you have to take a few seconds to figure it out though.

Efficiency

alias gcma='git commit -a -m'

Surely it's more efficient to type gcma than git commit -a -m? Isn't that obvious? Well it is if you've committed it to muscle memory. Before that, there's a learning period where your abbreviation is something you have to look up or work out each time.

Predictability

If it's an alias, will you remember that the message parameter to gcma is mandatory and must be included in quotes because it's a single parameter?
If you build this as a shell function...

gcma() {
  git commit -a -m "$@"
}

...instead of an alias to include the quotes, so you can type gcma foo bar baz, what will it do if you include them a second time, or if you forget the message completely?

What if you want to pass another parameter to git commit, like --squash? You can do it with the alias there but not the function as it stands. The cleverness of saving typing the extra quotes limits your options.

When you have a long list of these shortcuts, can you predict the behaviour of all your aliases without testing them for yourself?

Availability (Local)

If you're used to using an alias for something, and you try to use it somewhere outside your terminal session, are you sure you know what will happen? An alias in a script or a cron line will either not work or do something else if it's shadowing an executable. Are you confident enough that you won't make a mistake because you've come to rely so heavily on the alias that it's second nature?

Portability (Remote)

When you use a foreign system, your aliases aren't there. If you shell into a VPS or a local container for some reason, what are you going to do? What if you've been swayed by all those articles promoting zsh and decide you want to try using a different shell?

Shadowing (between systems)

What if you don't notice that your alias isn't there but the command you typed didn't do what you expected because you've shadowed it locally? You think for a minute, pull up the man page and browse through it wondering how everything used to work and whether you're forgetful or going a little mad.

Audit trails

Looking through your shell history to find out what you did last week when you had the same problem - can you remember what to search for? Was it the cryptic alias or the full command? What, exactly, was shadowed?

Let me borrow from the Zen of Python:

Explicit is better than implicit.
Readability counts.

Mostly these warnings come down to remembering when and where you're using an alias. Aliases can be very handy, but... just be careful, ok?

Cover image (largely unrelated) from ArielleJay at morguefile.com

Posted on Sep 3 '18 by:

moopet profile

Ben Sinclair

@moopet

I've been a professional C, Perl, PHP and Python developer. I'm an ex-sysadmin. Back in the day, I had a geekcode which I'm not going to share with you. 418 I'm a teapot.

Discussion

markdown guide
 

All valid points. The main reason why people resort to aliases is how unintuitive git command line interface is. For example I have an alias called git unstage because git reset HEAD -- doesn't actually explain anything at all to me, no matter how many times I look at it. I did always end up googling "how to unstage files" or "how to undo last commit" in the past.

Same goes for "git cherry", the documentation for cherry is Find commits yet to be applied to upstream. They could have called it "git whatever", it speaks to me as little as the word cherry does.

Some aliases are also to shortcut long commands, like git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short.

I agree that you can go overboard with aliases, but I still think there's value in having them

 

It's worth noting, also, that git aliases are (or should be) aliased within git, as it adds a lot of nice features:

$ git alias
unstage = reset HEAD --

$ git unstage --help # or
$ git help unstage
'unstage' is aliased to 'reset HEAD --'

$ git unstag
git: 'unstag' is not a git command. See 'git --help'.

The most similar command is
    unstage

That's a lot less terribad than wrapping the same thing in a shell alias or function. Shell aliases for git commands are especially dumb because you're both circumventing many of git's better features, and creating something that's susceptible to all of the issues raised here.

(It's almost as if, knowing their command structure might be... let's say "less than intuitive", the git developers at least decided to include good tools for mitigating that problem.)

 

Actually I guess git alias is part of git-extras, not core git. I guess I never noticed before, since it's just sort of always been there.

 

I am so-so on aliases; I think they make a lot of sense for stuff like git unstage -- ie, taking something and adding a name and meaning that is clearer. Sort of like how if there is a function from an API I am using all the time whose name I find confusing/unclear, I will just make a tiny wrapper function with a name that makes sense, etc. Stuff like gcma to me is sort of like taking document.getElementById and shadowing it to document.gebi

 

Yeah, I try not to alias git commands to acronyms, it makes my life harder.

 

That's a reasonable argument, and used like that it's definitely a beneficial approach. The aliases that most people mention, however, seem to be minimalistic acronyms, which suggests character reduction as the primary goal.

 

My approach to this kind of issue is to sort of "proceed with caution". Like, if you choose to use aliases do so while also being aware of the issues you are describing. Same reason you shouldn't go scuba diving without a pretty decent understanding of how your equipment works (and why it works the way it does). Any time things don't go perfectly to plan, you'll be glad you know the why and how.

Same goes for lots of abstractions. You don't need textbook knowledge of the implementation, but much of what you describe is present across most of software development.

 

I have a lot of aliases and functions. I have a script that generates them based on the system in question so I can avoid runtime checks of whether the necessary applications are present. Most of my aliases come from this script. The only drawback is I have to remember to run this script and source my aliases again once in a while.

The script has a list of 'simple aliases', where this list of tuples has the required application, the name of the alias, and the actual command:

simple_aliases = (('jhead', 'strip-exif', 'jhead -purejpg'),)

then it checks for the binary in PATH and adds the alias if it finds it.

I do not yet generate the functions output but I probably will soon, based on the dependencies.

Nowadays I prefer functions unless the alias is very simple like alias la='ls -la' or something I really don't feel like remembering: alias ltr='-l --sort=time -r.

The problem may be that completions are generally not available in Bash by default, and I know I find them invaluable, and I write my own quite a bit.

 

Great! I also rely on history and filter (do not capture) ls and some often used commands to make it shorter

 

Actually, I did start using them to avoid remembering some Linux commands that did require a lot of parameters and that I had to use seldom. For example: removing my old kernels to free up boot space. I did note that the linux community usually implement new commands or apps for those cases.

With the time, I did start to use them in the commands that I have to type frequently.

Later, I have grouped many of them, and automated all the development task that I do on a daily basis:

  • pull the upstream changes for all my repositories
  • rebase my local branches
  • calling commands from my docker containers
  • listing my local development databases
  • taking the snapshopt of one database in the current state (that allows to reproduce the error)
  • restoring the database to the snapshot state

... and many more

The generated aliases are loaded by my .bash_aliases and their names sometimes are dynamically build according to some parameters (e.g.: the name of the active containers that have the programs they call). With a selected naming convention (with '_') the auto-completion avoids me to type a lot.

At the end, I have use metadata from the different projects that we have, and used a template system to generate the development environment with all the alias prepared.

Some of my workmates use it, they replicate the dev configuration with just few commands, even in new workstations. They also give me feed back, and I try to improve it. I encourage them to improve it also.

I like it because the scripts also installs all the dependencies or generate the docker-compose.yml with all the needed stuff.

Many of my workmates don't like it, because they think they will forget how to use the original commands. I am also afraid of that :-D

But Actually, as soon as possible I will try the dodo commands because I think it seems to be the correct solution for that.

 

I have a few aliases and one- or two-line scripts that I use for repetitive tasks every day, but the way I most often work is to group them together in one line, for instance to pull my config files, I run:

(cd ~/.dotfiles && git checkout master && git pull origin master && ./install.sh)

since it's in a subshell (the parentheses) it doesn't leave me in a different directory when it's finished and since it uses && throughout it doesn't do anything unless the previous command succeeded. I call this up by doing <ctrl-r>dotf<cr> and rely on it being in my shell history rather than making it an alias.

 

Excellent points! Nice write up.

Regarding audit trails and recusion, that's mainly why I transitioned to fish shell abbreviations instead of regular aliases. It's basically more like a text expansion than actually changing the meaning of a set of characters.

Regarding predictability in portability, I try to only use mnemonic patterns with the first letter of each word. For example, I run gaaand in my head say git add --all as I type. This keeps them quite predictable, and on the rare occasion that I don't have my aliases the command is still in muscle / mental memory in a weird kind of way.

That being said, if I didn't have nerve damage in my hands that slows down my typing, I would probably be use them a lot less for many of the reasons stated above.

 

I try to not customize any of my tools, neither ides, because I get used to it and then when I change of machine (borrowed, workpc, homepc, servers) I get stuck. Yes you can import or reconfigure but in an emergency you don't have time.

It's really good idea to use aliases for long and complicated commands. Some are unnecessary "commit" for "com" seriously? It's commit difficult? How many commits we do to need that?

I always carry a txt with large commands, for ssh cli, etc.

 

Due to the nature of my work (primarily writing deployment-automation for a number of different customers) I work across a lot of (typically short-lived) systems in a given period of time. Relying on aliases is pretty much a non-starter for me. Yeah, I could ship around alias files, but, ultimately, it's all a hassle. Given that I've been using many of my tools for a very long time, aliases typically don't save me enough effort or time to be worth the hassle of shipping me-standard aliases (or encountering a system I couldn't ship to).

 

I also wanted to write an article like this after I same the many git alias articles on dev.to 😜

As I started as a developer I also used a lot of aliases. Nowadays, I don't use them anymore for these reasons:

  • If you want to help a colleague on another computer you often do not have your aliases and maybe don't remember the code behind your alias
  • Using autocompletion is nearly as fast as using an alias
 

There is a good rule: type whatever you want in your terminal, but use only standard commands and long versions of key names in your scripts.

Following this rule you will both save typing and don't forget the basics. + sharing your commands with others won't be painful for both sides

 

Great article. I have been bitten by aliases more than once.

I remember pulling my hair out over a failing mount command for several hours on a collocated server where a sys admin had aliases the mount command. I tried everything to get my USB drive to mount to no avail.

Finally I tried type mount and learned that mount was aliased. :mad:

The alias caused all my args and options to be misinterpreted by the system and I kept getting unexplainable usage errors.

This experience alone caused me to question aliases as a good practice to avoid typing long options.

I personally create mini shell scripts when I find something repetitive and give the shell script a clever unique name to avoid this nonsense.

 

I've been tripped up by scripts that have been given to me with local functions and aliases applied. That's my primary reason for being explicit, even at the expense of extra typing.