Reputation: 21
I aim to add a rudimentary change log to the top of every file, e.g.:
# Changelog:
# Last Modified on: 31.2.2020
# Last Modified by: Arthur Dent
# Last Modification: "After a Trillian tries, it works"
# File created: 01.01.1970
def whale2pot(args) ....
Now, in order to not have to do that manually, I would like to include the output of
git log -1
to the files concerned by this commit. (Not sure whether including the commit message is smart though..)
One way of doing this is via a bash script, which prepends the output of the above to the file(s). But this modifies the file(s), and the repo would never be actually up to date.
Hence: Is there a way to "overload" git commit
or somehow sneak this in without git noticing?
Thanks in advance =)
Upvotes: 1
Views: 852
Reputation: 21
After some tinkering, I chose this format (here it is for .m files):
%% ------------------------------------------------
%
% Created on: <date_of_creation>
% Author: <author>
%
% Last modifier: <modifier>
% Last modified: <date_of_last_mod>
% On Branch: <branch>
%
%%-------------------------------------------------
... and realized that I don't need the commit meta-data to achieve my goal. I get:
$(date)
$(git config user.name)
$(git rev-parse --abbrev-ref HEAD)
Still I followed @LeGEC's approach of having one script which does two things, as follows:
<date_of_creation>
and <author>
.For the time being, I run this manually before running git add <modified files>
.
I append the code below. This is my first bash scripting experience so feel free to point out what could be improved <=)
#!/bin/bash
#If there are no .m files for which this would apply, suppress the this notification (If i get that right)
shopt -s nullglob
#Act on untracked files
files=($(git ls-files --others --exclude-standard))
for item in ${files[*]}
do
#For time being, only consider matlab files
if [[ $item == *.m ]]
then
#Check whether the header already exists
read -r first_line < $item
first_cl_line="%% ------------------------------------------------"
if [ "$first_line" = "$first_cl_line" ]
then
continue
else
#Include Changelog into file
cat changelog_template.txt > tempfile
cat $item >> tempfile
mv tempfile $item
#Fill in static fields of inception date and author
sed -i "3,4d" $item
sed -i "2 a % Created on: $(date)" $item
sed -i "3 a % Author: $(git config user.name)" $item
#Update current changelog
./update_changelog.sh $item
fi
fi
done;
#!/bin/bash
USER=$(git config user.name)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
#Remove outdated lines and replace with updated ones.
for item in $(git ls-files -m)
do
sed -i "5,8d" $item
sed -i "5 a % Last Modifier: $USER" $item
sed -i "6 a % Last Modified: $(date)" $item
sed -i "7 a % On Branch: $BRANCH" $item
sed -i "8 a %" $item
done;
Upvotes: 1
Reputation: 52216
It can be surprisingly hairy to have such an obvious source of merge conflicts in your repo,
and it is very easy to extract the info from git while you browse your repo (git log -1 the/file
).
Before digging into how to actually store that info in the file's content,
perhaps you could settle for a handy shell shortcut, or for an outline integrated to your editor ? vscode
for example has the git lens
extension which gives you something pretty close (per line annotations, actually)
The creation date would be pretty static, so it could be inserted at a file's creation and kept that way ;
for the other parts of the header : I think a filter
would be the closest to the right way to do it
Official docs here : gitattributes
See an explanation in this SO answer : Can git filter out certain lines before commit?
You would write two scripts :
clean
script, would replace the header lines with constant values (eg : # Last Modified :
with no date)smudge
script, would run git log -1
and fill the lines with the desired valuesThe clean
script will be run when staging a file, and would make sure that the blobs stored in git have a constant header, to avoid problems when merging, rebasing, etc
The smudge
script will be run when checking out a file, and will write the correct content in the worktree version -- the file on disk, which you would actually open in your editor.
The main point not sorted in this answer is : the smudge script receives the file's content on stdin, not the file's name, so I don't see a clean way to run git log -1 file/name
from that script yet.
Upvotes: 1