1
votes

I'm a total Linux/Terminal amateur, and I would like to have a quick way to do the following two things:

  1. For all files that appear listed as with "changes not staged" when I do 'git status', show a list of each file name, their last commit date, and their last modification date.
  2. The same as as #1, but having the option to manually specify a file for which I want to show last commit and last modification date.

Thus far, I have been able to set up an alias that shows the last commit date for a given file (although this does not list the filename):

alias lastc='git log -1 --format=%cd'

I also managed to get the two dates I want in one go for a given file, with:

lastc do/9_sample_selection.do && date -r "$_"

But I don't know how to do this last thing with a simpler alias (e.g. lastdates filename), how to do it for all files that would appear when doing 'git status', and how to display the filenames in the output next to the dates.

Any help would be very much appreciated.

1

1 Answers

0
votes

First,

git status --porcelain=v1 -uno | cut -c4-

can be used to get the list of tracked filenames, either staged or unstaged;

git status --porcelain=v1 -uno | grep -e '^.[^ ]' | cut -c4-

can be used instead if you want to skip the staged files.

Then, you can combine the commands you mentioned (git log -1 --format=%cd and date -r) in a git alias with a bash one-liner:

$ git config --global alias.lastdates '!f(){ if [ $# -gt 0 ]; then printf "%s\n" "$@"; else git status --porcelain=v1 -uno | grep -e '\''^.[^ ]'\'' | cut -c4-; fi | tr '\''\n'\'' '\''\0'\'' | xargs -0 bash -c '\''for arg; do echo -e "$arg:\n  $(git log -1 --format=%cd --date=iso-strict HEAD -- "$arg") -> $(date -Is -r "$arg" 2>/dev/null || echo "N/A")"; done'\'' bash; }; f'

$ git lastdates
$ git lastdates file-names…

For more details

to elaborate a bit on the script:

$ git config --global alias.lastdates '!f(){ \

boilerplate − see e.g. this page

if [ $# -gt 0 ]; then printf "%s\n" "$@"; \

handle the file-names… arguments (print each of them in a separated line)

else git status --porcelain=v1 -uno | grep -e '\''^.[^ ]'\'' | cut -c4-; fi \

same code as above, escaping quotes

| tr '\''\n'\'' '\''\0'\'' | xargs -0 bash -c \

pass each line (filenames that might contain spaces) to the following script

'\''for arg; do \

iterate on each argument (filename)

echo -e "$arg:\n  $(git log -1 --format=%cd --date=iso-strict HEAD -- "$arg")

print the filename and commit date from current branch (HEAD)

-> $(date -Is -r "$arg" 2>/dev/null || echo "N/A")"; done'\'' \

print the date of the filename, or N/A in case of error (if the file was committed-then-deleted)

bash; }; f'

boilerplate code − this last bash string is necessary as it will be promoted as $0 when running the "inline script" (bash -c "…" bash other-arguments…)