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
- 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'
- Re-run with force once you accept losing the old hook: 'overcommit --install --force'
- 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
- Uninstall the previous hook framework (e.g. husky) or move custom hooks aside before adopting Overcommit
- Never rely on files in .git/hooks surviving an install
- Use --force deliberately, never in bootstrap scripts that run on teammates' machines
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
- Hook specified a `required_executable` or `command` that is
- Unable to write to local repo git config: #{result.stderr}
- Unable to read from local repo git config: #{result.stderr}
- does not appear to be a git repository
- Class #{hook_name} is not a subclass of #{hook_base_class}.
AI-assisted analysis of sds/overcommit@fee0cd74b2 (2026-08-23).
Data as JSON: /api/errors/2088a0f10e89871e.
Report an issue: GitHub.