Most of the solutions given so far are unreliable when they don't introduce arbitrary command injection vulnerabilities, either because they call read
without IFS=
and/or without -r
, assume file names don't contain newline characters, forget to quote parameter expansions or command substitutions, forgot the --
option delimiter, don't check exit status or embed the file names in shell code or --format
arguments.
This is just a safer variant of the approach given in most answers. Assumes a GNU system:
git ls-tree -zr --name-only HEAD |
xargs -n20 -r0P10 sh -xc '
ret=0
for file do
d=$(git log -1 --format="@%at" -- "$file") &&
touch -d "$d" -- "$file" || ret=$?
done
exit "$ret"' sh
Here also doing a few in parallel as the task is mostly CPU-bound.
To do it again after a git pull
to only update the recently touched files (here based on ctime and assuming GNU find
4.9 or newer), you can insert:
find -files0-from - -prune -cmin -5 -print0
As a pipeline component between git ls-tree
and xargs
to filter the files last updated in the last 5 minutes.
git log -n1 -- file
; that is whatgit
is for. – Florri