Skip to content

Support prepare-commit-msg hooks - #2795

Merged
lucasderraugh merged 2 commits into
git-up:masterfrom
DCVortexxx:prepare-commit-msg-hook
Sep 30, 2026
Merged

lucasderraugh merged 2 commits into
git-up:masterfrom
DCVortexxx:prepare-commit-msg-hook

Conversation

@DCVortexxx

@DCVortexxx DCVortexxx commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

Disclosure

I AGREE TO THE GITUP CONTRIBUTOR LICENSE AGREEMENT.

Full disclosure, this has been drafted by AI because I haven't played with ObjC for yeeeeeaaaaars, but I believe that it respects the coding standard and contribution rules.

Of course, I'm open to suggestions and will happily update it to make it into master.
I LOVE GitUp and having to rely on another editor just because a project I work on needs this hook on it is a pain 😅

Summary

This adds support for Git's prepare-commit-msg hook when creating commits from GitUp.

Git documents prepare-commit-msg as running after the default commit message is prepared and before the editor starts.

To match that lifecycle, GitUp now runs the hook when the commit view prepares the message editor in viewWillAppear :

  • The hook runs asynchronously so the commit view remains editable:
    • If the user starts typing before the hook finishes, GitUp preserves their input and inserts the prepared hook output before the user's content.
    • If the hook is still running when the user tries to commit, GitUp prevents the commit and asks the user to wait, since an installed prepare-commit-msg hook should be allowed to finish.

It also runs when the user toggles Amend:

  • GitUp first seeds the editor with the HEAD commit message, as it already did before this change.
  • It then reruns prepare-commit-msg with Git's amend-style commit source
    • If the message currently shown was only auto-filled by the first prepare-commit-msg run, GitUp replaces it with the amend message flow.
    • If the user has already typed their own content, GitUp preserves it instead of overwriting it.

This also has a side effect on the commit-msg hook, because it used to rely on a app-owned, temporary file for writing the commit message, instead the the $GIT_DIR/COMMIT_EDITMSG file Git uses.
Since prepare-commit-msg relies on this file, commit-msg should read it as well, as the single source of truth for commit message edition.

Note

My first implementation ran it when the user actually commits, right before commit-msg, and it made the code significantly simpler, since we don't need to handle in-flight edit, and "just" update the message in the same way commit-msg does.

However, I changed it to be closer to Git's semantics.
Feel free to let me know if you feel like this is a tradeoff worth having.

Run prepare-commit-msg when GitUp prepares the commit message editor so hook output appears before the user submits the commit.

Keep commit-msg validation at commit time using Git's standard COMMIT_EDITMSG file, and preserve user edits if the async prepare hook finishes after typing begins.
@lucasderraugh

Copy link
Copy Markdown
Collaborator

@DCVortexxx Thank you for the candor in using AI. It gives me the appropriate expectation. I assume you've tested locally?

It sounds like a good addition and I will look at the changes soon. This Thursday I'll likely be releasing the 1.5.0 release of GitUp to the stable channel so it won't go in before that.

Probably next week is a realistic time for me to start testing out this change.

@DCVortexxx

DCVortexxx commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Hey @lucasderraugh, thanks for getting back to me.

Yeah, I tested it locally, through all paths that came to mind :

  • Happy path
    • hook runs quickly and updates the commit message when you open the commit view.
  • Amend commit
    • hook re-runs with commit argument and the amended commit SHA
  • Long hook
    • commit is prevented while the hook is still running.
    • prepared message is inserted above the user input if there were modifications
  • Failed hook
    • Error is shown as soon as the hook fails
    • Commit is prevented
      • I wondered if we should allow the user to commit anyway here.
      • The error was already shown once on hook failure, so if the user actually wants to commit, that's up to him.
      • Especially because re-running the hook requires closing and re-opening the commit view, which is probably not that intuitive.
      • Change is trivial, I'll let this product decision up to you
  • Multiple hooks:
    • prepare-commit-msg, pre-commit, commit-msg, and post-commit still works
    • They are executed in the correct order
  • Merge commit :
    • Started outside GitUp
      • All hooks work correctly, including prepare-commit-msg
    • Started with GitUp GUI
      • The merge message input is generated through a dedicated popup, without going through the commit view.
      • In that scenario, no hooks are executed at all, including prepare-commit-msg.
      • IMO, that's a dedicated fix / feature, not in the scope of this PR

I also have validated that the implementation is reasonable, according to my knowledge of the codebase of course.

Let me know if I can help in any way, and of course, no worries about the timing,
Max

@lucasderraugh

Copy link
Copy Markdown
Collaborator

Wonderful, thank you!

@lucasderraugh

Copy link
Copy Markdown
Collaborator

@greptile Can you review this PR?

@greptile-apps

greptile-apps Bot commented Jul 27, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds support for Git prepare-commit-msg hooks in the commit UI.

This PR is safe to merge with minimal risk

Findings

  1. P2 Strong capture of self in nested dispatch blocks ▶
  2. P2 Missing squash and template source types for prepare-commit-msg ▶
Summary

This PR adds support for Git's prepare-commit-msg hook to GitUp's commit workflow. The hook runs asynchronously when the commit view appears and when the user toggles amend mode, preserving any user input typed before the hook completes.

  • Runs prepare-commit-msg hook asynchronously in viewWillAppear with generation-counter based cancellation to handle stale completions
  • Blocks commits while the hook is running to ensure hook output is available
  • Handles amend mode by re-running the hook with the appropriate Git source type (commit) and preserving user edits
  • Changes commit-msg hook to use $GIT_DIR/COMMIT_EDITMSG instead of temporary files, aligning with Git's standard file usage
Diagram
sequenceDiagram
    participant User
    participant View as CommitViewController
    participant BG as Background Thread
    participant Hook as prepare-commit-msg
    participant Commit as Commit Flow

    User->>View: Opens commit view
    View->>View: Set initial message
    View->>BG: Run hook asynchronously
    BG->>Hook: Write COMMIT_EDITMSG, execute hook
    
    alt User types before hook completes
        User->>View: Types message
        View->>View: Store user input
    end
    
    Hook-->>BG: Returns prepared message
    BG->>View: Apply prepared message (main queue)
    View->>View: Insert hook output before user content
    
    alt User toggles amend
        User->>View: Toggle amend on
        View->>View: Load HEAD message
        View->>BG: Re-run hook with "commit" source
    end
    
    User->>Commit: Click commit button
    
    alt Hook still running
        Commit->>User: Show "hook still running" alert
    else Hook completed
        Commit->>Hook: Run pre-commit
        Commit->>Hook: Run commit-msg (COMMIT_EDITMSG)
        Commit->>Commit: Create commit
    end
Loading

Reviews (2) · Last reviewed commit: "Only show prepare-commit-msg failure onc..."

Comment thread GitUpKit/Views/GICommitViewController.m
Comment thread GitUpKit/Views/GICommitViewController.m Outdated
Comment thread GitUpKit/Views/GICommitViewController.m
Comment thread GitUpKit/Views/GICommitViewController.m
@DCVortexxx

Copy link
Copy Markdown
Contributor Author

Hello @lucasderraugh, just wanted to check if you wanted me to address the Greptile feedbacks?

Both P1 are related to what I mentioned in this message:

  • Failed hook
    • Error is shown as soon as the hook fails
    • Commit is prevented
      • I wondered if we should allow the user to commit anyway here.
      • The error was already shown once on hook failure, so if the user actually wants to commit, that's up to him.
      • Especially because re-running the hook requires closing and re-opening the commit view, which is probably not that intuitive.
      • Change is trivial, I'll let this product decision up to you

The weak reference is an easy fix.

The third one however would require me to get back into the project.
I'm not sure the message option is relevant, but I'd have to look at the squash option though.

Absolutely no rush on that, just wanted to say that I'm still here if needed.
Thank you 🙏

@lucasderraugh

Copy link
Copy Markdown
Collaborator

@DCVortexxx Thanks, let me look through them myself tonight and I'll see what I think is still relevant.

Thanks for following up.

@lucasderraugh lucasderraugh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to resolve the error being kept around and just let the error show once on the hook failure and not again.

Other than those comments, I think this looks good to go.

Comment thread GitUpKit/Views/GICommitViewController.m
Comment thread GitUpKit/Views/GICommitViewController.m
Comment thread GitUpKit/Views/GICommitViewController.m Outdated
Comment thread GitUpKit/Views/GICommitViewController.m
@DCVortexxx

Copy link
Copy Markdown
Contributor Author

@lucasderraugh, I've added a dedicated commit to only show the failure, once, when the hook fails.
I've kept a separate commit so you can review it independently.

If it looks good to you, I'll squash them and rebase onto master.

@lucasderraugh
lucasderraugh merged commit 0650823 into git-up:master Sep 30, 2026
3 checks passed
@lucasderraugh

Copy link
Copy Markdown
Collaborator

All good, I can do that with one button.

Thanks for the changes. I have an outstanding continuous build I'm going to move to stable but then we'll kick off a new continuous build soon thereafter. I have some performance improvements I've been meaning to get in as well so we'll try those and this in that next build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants