13

I want to ensure that my latest commit has the current date before I push. Since I always rebase to master before a merge + push, I made this alias:

[alias]
    sync = !git commit --amend --date=today && git rebase master

Problem is, it keeps launching my text editor asking for a new commit message. Is there a way to have an optional parameter, so that I can choose to use either:

git sync 'my commit message'

or

git sync

where the latter will simply use the existing commit message, whatever it happens to be?

1

2 Answers 2

19

To apply the extra parameters to anything except the end of your alias’ “command line”, you will need to put your shell commands in a script. You can do it with an external script (like jdelStrother’s answer), or you can do it with an “inline” shell script.

You can use -m to feed git commit your new message or use the -C HEAD/--reuse-message=HEAD option to have it use the existing message and author (it would also reuse the author timestamp, but you are resetting that with --date=…). Using any of these options will prevent Git from opening an editor for your commit message.

Here it is as an “inline” shell script:

git config --global alias.sync '!sh -c '\''git commit --amend --date=today ${1+-m} "${1---reuse-message=HEAD}" && git rebase master'\'' -'

The core of this small script is the pair of conditional parameter expansions:

${1+-m} "${1---reuse-message=HEAD}"

When you call it with an extra parameter (i.e. your replacement log message), these expand to two shell words: -m "<your new log message>". When you do not supply the extra parameter, they expand to just a single word: "--reuse-message=HEAD".

The trailing dash is also important; it could be any shell word, the point is that something must be there because the shell will use it to initialize its $0 parameter (which usually has a default value, so it is useless for the conditional expansion itself).


If I misunderstood and you actually want to see the editor when you do not supply the extra parameter, then use the single expansion ${1+-m "$1"} instead of the pair of expansions.

Sign up to request clarification or add additional context in comments.

3 Comments

--reuse-message=HEAD is just what I was looking for, however the script isn't working how I expected. The commit command seems to use the existing message regardless of whether I supply a parameter, and the rebase command always comes back with an error: When no parameter is supplied I get 'fatal: Needed a single revision invalid upstream master' When a parameter is supplied I get 'Usage: git rebase ...'
@ceramica It works for me (both giving a new message and reusing the old message, as well as the subsequent rebase), but I have to use something besides --date=today, since that is not valid. I used --date="$(date "+%s %z")" instead — the exact command I used to create the alias (that is working for me) is git config --global alias.sync '!sh -c '\''git commit --amend --date="$(date "+%s %z")" ${1+-m} "${1---reuse-message=HEAD}" && git rebase master'\'' -'.
I finally got it to work but I had to manually change the alias in my .gitconfig to: "!sh -c 'git commit --amend --date=today ${1+-m} \"${1---reuse-message=HEAD}\" ; git rebase master' -" I don't know why it needs the extra quotation marks, but the need for ; to separate the commands suggests the first one is failing. Yet, it seems to work fine.
6

When your aliases start getting more complex, it's probably easiest just to create a separate script for them. If you add a file 'git-sync' to your path, it will be automatically called when you do 'git sync'.

So, if you created that file with something along the lines of -

#!/bin/sh

if [ -z "$1" ]; then
  git commit --amend --date=today
else
  git commit --amend --date=today -m "$1"
fi
git rebase master

- that would probably work. It's typed off the top of my head though, so caveat lector.

1 Comment

The idea is sound, but this script does not do the conditional execution (&&) like the OP’s original code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.