Maikol Solís
Maikol Solís

Reputation: 71

Is there a way to have a commit per day and per file automatically in git?

I use git-auto-commit-mode (https://github.com/ryuslash/git-auto-commit-mode) in Emacs to preserve my files automatically sync with my repo.

However, I got a massive list of commits per day (the package makes a commit in every save). At the end of the day I finish with something like this

Sat Feb 4 12:57:14 2023 fileA.txt
Sat Feb 4 12:56:52 2023 fileA.txt
Sat Feb 4 12:55:57 2023 fileA.txt
--------- Different file --------
Sat Feb 4 12:54:47 2023 fileB.txt
Sat Feb 4 12:45:04 2023 fileB.txt
Sat Feb 4 12:45:04 2023 fileB.txt
Sat Feb 4 12:44:51 2023 fileB.txt
--------- Different day ---------
Fri Feb 3 14:44:27 2023 fileA.txt
Fri Feb 3 14:44:05 2023 fileA.txt
Fri Feb 3 14:41:35 2023 fileA.txt
--------- Different file --------
Fri Feb 3 14:40:54 2023 fileB.txt
Fri Feb 3 14:40:17 2023 fileB.txt
Fri Feb 3 14:39:14 2023 fileB.txt

I would like to have a cleaner history like this

Sat Feb 4 12:57:14 2023 fileA.txt
Sat Feb 4 12:54:47 2023 fileB.txt
Fri Feb 3 14:44:27 2023 fileA.txt
Fri Feb 3 14:40:54 2023 fileB.txt

Where I preserve the last commit day per day and per file.

I can do this using git rebase manually, but I couldn't figure it out how to do it automatically for the whole history, taking account deletions and renames.

Thanks for any help.

Upvotes: 1

Views: 212

Answers (2)

Maikol Solís
Maikol Solís

Reputation: 71

Thanks to VonC (https://stackoverflow.com/a/75349092/7529776) I have a partial solution to the problem

After loading git-auto-commit-mode you can do this

(defun my-commit-message (file)
  (interactive)
  (let ((current-day (format-time-string "%Y-%m-%d"))
        (previous-day (file-name-nondirectory (shell-command-to-string "git log -n 1 --pretty=format:'%as' HEAD")))
        (current-file (file-name-nondirectory file))
        (previous-file (file-name-nondirectory (shell-command-to-string "git log -n 1 --pretty=format:'%s' HEAD"))))
    (if (and (string= current-file previous-file)
             (string= current-day previous-day))
        (concat "squash! "  (gac-relative-file-name file))
      (gac-relative-file-name file))))

(setq gac-default-message #'my-commit-message)

and then you can run

git -c sequence.editor=: rebase --autosquash --interactive origin/main 

Or use magit's rebase with the autosquash flag.

The problem remaining is this method only modifies the history from the present, but not in the past.

Edit: I added a new version of my-commit-message where it checks if the day also has changed.

Upvotes: 1

VonC
VonC

Reputation: 1324278

If you can add a prefix to the commit messages of git-auto-commit-mode, then you can get:

squash!Sat Feb 4 12:57:14 2023 fileA.txt
squash!Sat Feb 4 12:56:52 2023 fileA.txt
Sat Feb 4 12:55:57 2023 fileA.txt
--------- Different file --------
squash!Sat Feb 4 12:54:47 2023 fileB.txt
squash!Sat Feb 4 12:45:04 2023 fileB.txt
squash!Sat Feb 4 12:45:04 2023 fileB.txt
Sat Feb 4 12:44:51 2023 fileB.txt

That means your defun my-commit-message must check if the commit right before the new one is:

  • for the same file (add a squash! prefix) or
  • for a different file (don't add the prefix)

Then a git -c sequence.editor=: rebase --autosquash --interactive origin/main would be enough to automatically squash your history as you want it.

Upvotes: 0

Related Questions