5 ms·
Back dating Git commits based on file modification dates
- spullara 2y agoLove that they included the Claude workflow they used to write the script.
- j0057 2y agoI think using pathlib instead of the more old-school os.walk and os.path.getmtime would clean that code up substantially!
- simonw 2y agoI agree, and if I’d written this code by hand I would have used pathlib. I basically stopped caring as soon as I ran Claude’s code and it did the thing I wanted it to do.
- sitkack 2y agoSome updates, including using pathlib. https://claude.site/artifacts/e7b11dfa-0ab8-46ed-97bc-5c101183e704 https://claude.site/artifacts/e7b11dfa-0ab8-46ed-97bc-5c1011...
- susam 2y agoNot exactly what's in this original post but here's a little shell function that could be useful to conveniently backdate Git commits: dated() { date=$1 shift 1 set -x GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" "$@" unset date } Some usage examples: dated "1990-01-01 10:10" git commit dated "1990-01-01 10:10:00 +0100" git commit dated "1990-01-01 10:10:10 +0100" git commit --amend dated "1990-01-01 10:10:10 +0100" git commit --amend --reset-author
- Izkata 2y agoIf all you want is author date (which I think is more correct), then just this works fine: git commit --date '1990-01-01 10:10'
- j0057 2y agoIIRC the GitHub UI started showimg commit date instead of author date some years ago.
- thaliaarchi 2y agoI use the following to create a commit using the latest modification date of the staged files. If you put it in your PATH as git-tcommit, you can invoke it as `git tcommit`. If GIT_AUTHOR_DATE or GIT_COMMITTER_DATE is passed, it overrides the modified time, and it honors TZ. It works with GNU or BSD. #!/usr/bin/env bash set -eEuo pipefail # `git commit`, using the latest file modification time as the commit and author # dates, when GIT_AUTHOR_DATE or GIT_COMMITTER_DATE, respectively, is not set. # Use fractional seconds when available to display the newest file more # accurately, even though Git only uses seconds. if which gstat >/dev/null; then stat=(gstat --format='%.Y %n') # Detected aliased GNU coreutils elif stat --version 2>/dev/null | grep -q 'GNU coreutils'; then stat=(stat --format='%.Y %n') # Detected GNU coreutils else stat=(stat -f '%m %N') # Fallback to BSD-style, which only reports seconds fi # Select the latest modified time of all staged files, excluding deletions. modified="$( cd "$(git rev-parse --show-toplevel)" && git diff --staged --diff-filter=d --name-only -z | xargs -0 "${stat[@]}" | sort -rn | head -1 )" modified_seconds= if [[ -n $modified ]]; then modified_seconds="${modified%% *}" modified_file="${modified#* }" modified_date="$(date -r "${modified_seconds%.*}" +'%Y-%m-%d %H:%M:%S %z')" echo "Modify date: $modified_date ($modified_file)" fi author_seconds="$modified_seconds" committer_seconds="$modified_seconds" if [[ -n ${GIT_AUTHOR_DATE+.} ]]; then echo "Author date: ${GIT_AUTHOR_DATE:-now}" fi if [[ -n ${GIT_COMMITTER_DATE+.} ]]; then echo "Commit date: ${GIT_COMMITTER_DATE:-now}" else last_commit_seconds="$(git show -s --format=%at HEAD 2>/dev/null || echo 0)" if [[ $modified_seconds < $last_commit_seconds ]]; then committer_seconds= echo "Commit date: now (last commit: $(git show -s --format=%ai HEAD 2>/dev/null))" fi fi GIT_AUTHOR_DATE="${GIT_AUTHOR_DATE-"$author_seconds"}" \ GIT_COMMITTER_DATE="${GIT_COMMITTER_DATE-"$committer_seconds"}" \ exec git commit "$@"
- jdorfman 2y agoWhen I saw the repo yesterday I thought how did Simon do that? Now I know. Great work mate.
- chx 2y ago[flagged]
- dang 2y ago"Don't be snarky." https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html Edit: we've been having to ask you to stop breaking HN's guidelines for a long time: https://news.ycombinator.com/item?id=40778889 https://news.ycombinator.com/item?id=40778889 (June 2024) https://news.ycombinator.com/item?id=34194251 https://news.ycombinator.com/item?id=34194251 (Dec 2022) https://news.ycombinator.com/item?id=29797582 https://news.ycombinator.com/item?id=29797582 (Jan 2022) https://news.ycombinator.com/item?id=27241824 https://news.ycombinator.com/item?id=27241824 (May 2021) https://news.ycombinator.com/item?id=19411598 https://news.ycombinator.com/item?id=19411598 (March 2019) https://news.ycombinator.com/item?id=17641642 https://news.ycombinator.com/item?id=17641642 (July 2018) https://news.ycombinator.com/item?id=16000997 https://news.ycombinator.com/item?id=16000997 (Dec 2017) https://news.ycombinator.com/item?id=14745494 https://news.ycombinator.com/item?id=14745494 (July 2017) https://news.ycombinator.com/item?id=14740536 https://news.ycombinator.com/item?id=14740536 (July 2017) https://news.ycombinator.com/item?id=14482567 https://news.ycombinator.com/item?id=14482567 (June 2017) If this keeps up, we're eventually going to have to ban your account. I don't want to do that since most of your comments are fine, but it's the bad ones that matter for moderation. If you'd please review https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html and stick to the rules from now on, that would be good.
- Nullabillity 2y agoWhat else is there to do against this flood of LLM spam?
- slater 2y agoFlag and downvote, and let the mods do their job.
- Dylan16807 2y agoHuh? The fact that someone used an LLM to write part of their code doesn't make their blog post "LLM spam". And it's complete nonsense to say the repository was "generated by an LLM". The code doesn't even touch the file contents, and it has straightforward functionality that was reviewed by a human.
- cxr 2y ago> clicking a link to a .m file triggers a download Firefox can be convinced to simply show you any resource that you know is some flavor of plain text if you open it in View Source mode, i.e. by constructing a view-source: URI out of the original URL and accessing it that way. So to bypass the download nag screen for Anchor.m, you'd access it as <view-source:https://www.w3.org/History/1991-WWW-NeXT/Implementation/Anchor.m https://www.w3.org/History/1991-WWW-NeXT/Implementation/Anch...> instead. This even works on Firefox for Android, but not Chrome. (Of course you don't need to construct these by hand most of the time; if you're on a page linking to a bunch of files that otherwise prompt you to download them, like the Apache directory listing in this case, you just view the source of the directory listing page and click the links in the href attribute values there.) This is pretty useful in multiple circumstances—which of course means that someone at Mozilla Corp will remove it from Firefox or find some other way to stop you from doing this any day now.
- jraph 2y ago> which of course means that someone at Mozilla Corp will remove it from Firefox or find some other way to stop you from doing this any day now Mozilla has its fatal flaws and I'm all for pointing them out (loudly), but it seems like time would be better invested at actually pointing the real flaws. For all their flaws, I don't think they are out there actively trying to piss people off, even if it can feel like they are. I don't see why they would remove this. It doesn't seem like supporting this use case causes any complexity in the code or in the UI / UX. Hatred is not free, I would suggest spending it wisely. (of course, I know you are probably being sarcastic)
- deleted 2y ago[deleted]
- cxr 2y ago[flagged]
- robertlagrant 2y agoYour response's logic applies to your response far more than to theirs.
- antman 2y agoVery nice, if one wants something more meaningful than only perhaps you can add a Claude summary aka https://github.com/RomanHotsiy/commitgpt https://github.com/RomanHotsiy/commitgpt
- Izkata 2y agoYou probably don't want to reset committer date like that. It tracks repo information, not file information, and is generally not visible in things like log and blame.
- simonw 2y agoI first tried just using author date but that didn’t display correctly in GitHub, and the whole point of this exercise was to get the GitHub web UI to show “33 years ago”.
- Izkata 2y agoWeird. Wonder why they did that. This is what it looks like using git directly: $ git init foobar Initialized empty Git repository in /tmp/foobar/.git/ $ cd foobar/ $ vim Bar $ git add Bar $ git commit --date '2021-01-01 01:01:01' -m'Bar' [master (root-commit) fd1d31c] Bar Date: Fri Jan 1 01:01:01 2021 -0600 1 file changed, 1 insertion(+) create mode 100644 Bar $ git blame Bar ^fd1d31c (Izkata 2021-01-01 01:01:01 -0600 1) Bar $ git log commit fd1d31c2d29e3e8f6325d9abca883ce7e00d48e3 (HEAD -> master) Author: Izkata <***> Date: Fri Jan 1 01:01:01 2021 -0600 Bar $ git log --pretty=fuller commit fd1d31c2d29e3e8f6325d9abca883ce7e00d48e3 (HEAD -> master) Author: Izkata <***> AuthorDate: Fri Jan 1 01:01:01 2021 -0600 Commit: Izkata <***> CommitDate: Sat Aug 3 12:50:45 2024 -0500 Bar
- generj 2y agoI’ve used a similar technique to create a git history for configuration files in an AWS S3 bucket that has version control enabled.
- deleted 2y ago[deleted]
- unqueued 2y agoThanks for sharing, I love stuff like this. I get frustrated at mtimes being munged. MacOS finder is terrible about this. If anyone is interested, I wrote a more generalized tool for storing metadata called storetouch[1] which takes a snapshot of file's mtimes, and stores them in a nicely formatted file for convenient restoration. You can run it's output by itself with bash, or easily parse it's output. I found that the commit or author date's did not always make sense to represent the true age of a file. Especially for non-source-code documents. For example, a repo of scanned documents. Or a git-annex repo of podcasts going back 20 years. Instead, I treat the commit date as the commit date, and I have a versioned sidecar that stores the actual original mtimes of the files. It can also handle all valid POSIX filenames (a surprising amount of utilities don't, including tools like git-restore-mtime, last time I checked). If you're already using a tool like git-annex or datalad though, they have the ability to store metadata for each file as well. I would also suggest checking out git-store-meta[2] which was the original inspiration. It stores more than just mtime, but it is more closely tied to git. [1]: https://github.com/unqueued/storetouch https://github.com/unqueued/storetouch [2]: https://github.com/danny0838/git-store-meta https://github.com/danny0838/git-store-meta
- Ferret7446 2y agoThe mtimes aren't being munged. mtimes are filesystem metadata that reflect when the file was changed; trying to use them as version control information (or application level metadata) is wrong. For example, mtimes are used by programs that cache file data, like file indexing programs; backdating mtimes will break everything that uses mtimes for their intended purpose.
- didntcheck 2y agoYep, and a lot of backup software will use them (along with file size, and other stat() fields) to determine if a file has changed, so backdating them can actually lead to silently stale backups
- yencabulator 2y agoIt's 2024, any backup mechanism that isn't based on a delta between two snapshots is legacy from the old bad times.
- jurakovic 2y agoI did something similar from backup files for one of my projects. Although I did it mostly manually. It's on GitHub now at https://github.com/jurakovic/Comets-Archive https://github.com/jurakovic/Comets-Archive
- escapecharacter 2y agoI had heard that git was incompatible with dates pre Unix (around 1970). This makes it hard if you want to use git as a format to show collaborate on documents historically. Has there been any progress on general agreement on how to do this? Ref: https://github.com/JesseKPhillips/USA-Constitution?tab=readme-ov-file#who-made-the-change https://github.com/JesseKPhillips/USA-Constitution?tab=readm...
- deleted 2y ago[deleted]
- IYasha 2y agoMisread the title thinking someone invented nerdy dating service on github. But it's not that. Disappointed.