Joshua Soileau
Joshua Soileau

Reputation: 3015

Git alias with bash script errors out on variable modification

My git branch name:

feature/ACD-1706_new-api-call
If I run this script in the console, it works properly:
bash -l -c 'current_branch="$(git rev-parse --abbrev-ref HEAD)" && no_feature=${current_branch##*/} && no_underscore=${no_feature%%_*} && history -s "git commit -m \"$no_underscore | " && echo "Press UP to start commit command:" && echo "" && read -e -p "> " && eval "$REPLY"'
It drops me in a prompt that helps me auto-generate a commit message based on the feature branch name.
> bash -l -c 'current_branch="$(git rev-parse --abbrev-ref HEAD)" && no_feature=${current_branch##*/} && no_underscore=${no_feature%%_*} && history -s "git commit -m \"$no_underscore | " && echo "Press UP to start commit command:" && echo "" && read -e -p "> " && eval "$REPLY"'
Press UP to start commit command:

> 

But if I turn it into a git alias, the script errors out.

auto-message = !bash -l -c 'current_branch="$(git rev-parse --abbrev-ref HEAD)" && no_feature=${current_branch##*/} && no_underscore=${no_feature%%_*} && history -s "git commit -m \"$no_underscore | " && echo "Press UP to start commit command:" && echo "" && read -e -p "> " && eval "$REPLY"'
> git auto-message
bash -l -c 'current_branch=$(git rev-parse --abbrev-ref HEAD) && no_feature=${current_branch: -c: line 0: unexpected EOF while looking for matching `''
bash -l -c 'current_branch=$(git rev-parse --abbrev-ref HEAD) && no_feature=${current_branch: -c: line 1: syntax error: unexpected end of file

Upvotes: 1

Views: 299

Answers (3)

chepner
chepner

Reputation: 531055

Using git commit's -e option would be far simpler if you just want to seed the commit message with some initial text. It also allows the user use their text editor of choice, rather than forcing readline on them.

git commit -em "$(git rev-parse --abbrev-ref HEAD | sed 's|.*/||; s|_.*$||;' )"

(One drawback is that this starts with a temporary file that contains the -m argument, so simply quitting the editor without saving isn't sufficient to abort a commit. You have to explicitly save an empty file to do that.)

This, then, is much easier to quote properly:

auto-message = !git commit -em "$(git rev-parse --abbrev-ref HEAD | sed 's|.*/||; s|_.*$||;')"

Upvotes: 2

Ralf
Ralf

Reputation: 1813

A different solution. This doesn't uses aliases, but just uses a script.

Create a file in your path with the name git-auto-message (no extension!) with the following content:

#!/bin/bash

#current_branch="feature/ACD-1706_new-api-call"
current_branch="$(git rev-parse --abbrev-ref HEAD)"
no_feature=${current_branch##*/}
no_underscore=${no_feature%%_*}

read -p "Complete commit message (empty cancels) \"$no_underscore | " msg
echo
# remove leading whitespaces
msg="${msg#"${msg%%[![:space:]]*}"}"
# remove trailing whitespaces
msg="${msg%"${msg##*[![:space:]]}"}"
if [ -n "$msg" ]; then
    git commit -m "$no_underscore | $msg"
fi

Make the script executable.

Then you can call git auto-message. Git realizes, that it doesn't have an internal command named auto-message and that there is no alias with that name. So it searches the path for an executable named git-auto-message. So the script gets executed.

While aliases are great for smaller things, this feature allows to create rather complex functionalities.


Updated script, as I missed, that you want to add additional text.

Upvotes: 1

joanis
joanis

Reputation: 12221

This is certainly a case of having to escape the right character here or there.

I suggest a simpler solution, also suggested by @user7369280 at the same time I posted the original version of this answer: create file git-auto-message somewhere on your PATH with these contents:

#!/bin/bash

set -o errexit

current_branch="$(git rev-parse --abbrev-ref HEAD)"
no_feature=${current_branch##*/}
no_underscore=${no_feature%%_*}
history -s "git commit -m \"$no_underscore | "
echo "Press UP to start commit command:"
echo ""
read -e -p "> "
eval "$REPLY"

Make this file executable

chmod 755 /path/to/git-auto-message

And then

git auto-message

will run that script with the same behaviour your original command line had.

I just worked on troubleshooting your actual alias, and I found that the git alias syntax does not like having these symbols: #, >, |.

This variant works but loses some of your features:

  • It does not remove the path at the beginning of the branch name. I have not found a way to search for the string up to the / using bash syntax that git aliases accept.
  • It uses - instead of | to separate the branch name from the rest of the commit.
  • It uses $ instead of > for the prompt.

Revised alias:

auto-message = !bash -l -c 'current_branch="$(git rev-parse --abbrev-ref HEAD)" && no_feature=${current_branch} && no_underscore=${no_feature%%_*} && history -s "git commit -m $no_underscore - " && echo "Press UP to start commit command:" && echo "" && read -e -p "_ " && eval "$REPLY"'

Upvotes: 1

Related Questions