sds/overcommit · warning · Overcommit::Exceptions::PreExistingHooks

Hook '#{File.expand_path(hook_type)}' already exists and was

Error message

Hook '#{File.expand_path(hook_type)}' already exists and was not installed by Overcommit

What it means

While copying each supported hook type from the master hook into the hooks directory, Installer refuses to overwrite a file that already exists and is not recognized as Overcommit-installed, raising PreExistingHooks with the full path. can_replace_file? allows replacement only with --force, when the file is absent, or when it looks like an Overcommit hook - this protects foreign hooks from being clobbered. A normal install first moves such files into old-hooks/ (preserve_old_hooks), so hitting this error means a conflicting file was still present at copy time.

Source

Thrown at lib/overcommit/installer.rb:115

        raise Overcommit::Exceptions::InvalidGitRepo, 'does not appear to be a git repository'
      end
    end

    def install_master_hook
      FileUtils.mkdir_p(hooks_path)
      FileUtils.cp(MASTER_HOOK, master_hook_install_path)
    end

    def uninstall_master_hook
      FileUtils.rm_rf(master_hook_install_path, secure: true)
    end

    def install_hook_files
      # Copy each hook type (pre-commit, commit-msg, etc.) from the master hook.
      Dir.chdir(hooks_path) do
        Overcommit::Utils.supported_hook_types.each do |hook_type|
          unless can_replace_file?(hook_type)
            raise Overcommit::Exceptions::PreExistingHooks,
                  "Hook '#{File.expand_path(hook_type)}' already exists and " \
                  'was not installed by Overcommit'
          end
          FileUtils.rm_f(hook_type)
          FileUtils.cp('overcommit-hook', hook_type)
        end
      end
    end

    def can_replace_file?(file)
      @options[:force] ||
        !File.exist?(file) ||
        overcommit_hook?(file)
    end

    def preserve_old_hooks
      return unless File.directory?(hooks_path)

View on GitHub (pinned to fee0cd74b2)

Solutions

  1. Inspect the file named in the error, back it up or fold its logic into an Overcommit plugin, then remove it and re-run 'overcommit --install'
  2. Re-run with force once you accept losing the old hook: 'overcommit --install --force'
  3. If the old hook must keep running, migrate it to an ad hoc hook or plugin in .overcommit.yml so Overcommit manages it

Example fix

# before
$ overcommit --install
Hook '/repo/.git/hooks/pre-commit' already exists and was not installed by Overcommit

# after
$ mv .git/hooks/pre-commit .git/hooks/pre-commit.bak
$ overcommit --install
Defensive patterns

Strategy: validation

Validate before calling

hooks_path = `git config core.hooksPath`.strip
hooks_path = File.join(`git rev-parse --git-dir`.strip, 'hooks') if hooks_path.empty?
foreign = Overcommit::Utils.supported_hook_types.select do |type|
  f = File.join(hooks_path, type)
  File.exist?(f) && File.read(f) !~ /overcommit/
end
abort "Foreign hooks present: #{foreign.join(', ')} - back them up first" unless foreign.empty?

Type guard

def foreign_hooks(hooks_path)
  Overcommit::Utils.supported_hook_types.select do |type|
    f = File.join(hooks_path, type)
    File.exist?(f) && File.read(f) !~ /overcommit/
  end
end

Try / catch

begin
  installer.run(target, action: :install)
rescue Overcommit::Exceptions::PreExistingHooks => e
  warn "#{e.message} - back up the hook or re-run with --force"
  exit 1
end

Prevention

When it happens

Trigger: 'overcommit --install' (or --update) when a non-Overcommit 'pre-commit'/'commit-msg'/... file exists in the resolved hooks path (core.hooksPath or .git/hooks) and --force was not passed - e.g. husky or hand-written git hooks, or a foreign hook file that survived the backup pass.

Common situations: Repo already uses husky or the pre-commit framework, or has custom git hooks, and Overcommit is added later; core.hooksPath points at a shared hooks directory containing foreign hooks; an Overcommit-installed hook was edited so heavily it is no longer recognized.

Related errors


AI-assisted analysis of sds/overcommit@fee0cd74b2 (2026-08-23). Data as JSON: /api/errors/2088a0f10e89871e. Report an issue: GitHub.