6

I am working on task in which I need the git commit date to be written into one of the files being committed. I need it to happen in a couple of scenarios:

  • While branch was pushed it into remote repo
  • While merging it into master

Specifically, the change should look like this:

Before commit: private String DATE="$DATE$"

After commit: private String DATE="$DATE: 2020-05-08 18:19:25 $"

Here's what I've tried so far:

I have followed https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Keyword-Expansion and added .gitattributes, .gitconfig, .git_filters(which has smudge and clean filter) into my project.

Below are the things which i configured in proj:

  • .gitConfig:
    clean  = .git_filters/dater.clean
    smudge = .git_filters/dater.smudge %f 
  • .gitAttributes:
*.java filter=dater 

  • .git_filters: (created separate folder under parent repo)
dater.clean:

#!/usr/bin/sh

sed s/$Date$/`date +%Y%m%d`/g 

dater.smudge:

#! /usr/bin/env ruby
data = STDIN.read
last_date = `git log --pretty=format:"%ad" -1`
puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')

When i tried with the above configuration.. it doesn't work..Looking for help to fix this issue plz...

3
  • Welcome to Stack Overflow. The title says java, the question was tagged shell but I don't see anything java or shell-related in the question body. I'm removing shell tag now, please add relevant tags and fix the title Commented May 10, 2020 at 15:23
  • I don't completely understand your problem, but have you tried git hooks? Commented May 10, 2020 at 15:26
  • @symlink I think git hooks is the way to go. Though there is a chicken-egg aspect to the problem, unless the commit date-doesn't have to be exact. Or does git-hook get around that somehow? Commented May 10, 2020 at 16:46

1 Answer 1

4

Smudge and clean filters are the right way to go here, but you're going to have to use a filter process as described in gitattributes(7). The reason this is required is that when smudging commits during a checkout, HEAD has not been updated, so it's not possible to query the date of the given revision.

In very recent versions of Git (definitely 2.26, but possibly 2.25), you can use the filter process to get the commit if it's available. If the commit ID is available, you can query treeish in the metadata passed to the filter process. That will be a commit if it's available, and a tree (or absent) if not. If it's not a commit, you should be able to use HEAD instead.

This metadata is not passed along using smudge and clean, only when using filter-process, so you really need to create a small process filter if you need this functionality.

Also, be aware that your clean filter should strip the date out and not actually include it in the commit. If you store the date in the actual commit, then you'll run into merge conflicts every time you merge branches.

Finally, all of this can be avoided and you can go with a much simpler solution if you don't need this DATE field in every class. If your project contains a single static class with metadata in it, you can put the DATE field there, create it as part of one of your build steps by invoking Git, and dispense with the filters altogether. This will be easier, faster, and simpler. If you need to produce a tarball, you can generate this file at tarball generation time.

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

4 Comments

Actually, classes having DATE field has build number.So whenever any changes made on that class, build number for that class will be changed manually.DATE field should be taken care by GIT.also there in no single static class in the project. I tried to find out the solution, but ended up with smudge and clean filter.
is there any better solution? I came across git hooks? will that help
As mentioned, you shouldn't put the date into each file when you commit it because it will cause merge conflicts every time you merge. So while it's possible to do with hooks, you'll end up with that value in the commit, which you don't want. Generating this data at build time is really ideal, but using a filter process is the only other real option if you don't want to.
Git doesn't do that the way CVS does. You can use the ident attribute, but other than that, you need a smudge/clean filter. I implemented the extended metadata in the filter process partially for this reason; before that, it just wasn't possible at all. Sorry to disappoint you; that's just the way it is.

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.