{"record":{"id":"2088a0f10e89871e","repo":"sds/overcommit","slug":"hook-file-expand-path-hook-type-already-exis","errorCode":null,"errorMessage":"Hook '#{File.expand_path(hook_type)}' already exists and was not installed by Overcommit","messagePattern":"Hook '#(.+?)' already exists and was not installed by Overcommit","errorType":"exception","errorClass":"Overcommit::Exceptions::PreExistingHooks","httpStatus":null,"severity":"warning","filePath":"lib/overcommit/installer.rb","lineNumber":115,"sourceCode":"        raise Overcommit::Exceptions::InvalidGitRepo, 'does not appear to be a git repository'\n      end\n    end\n\n    def install_master_hook\n      FileUtils.mkdir_p(hooks_path)\n      FileUtils.cp(MASTER_HOOK, master_hook_install_path)\n    end\n\n    def uninstall_master_hook\n      FileUtils.rm_rf(master_hook_install_path, secure: true)\n    end\n\n    def install_hook_files\n      # Copy each hook type (pre-commit, commit-msg, etc.) from the master hook.\n      Dir.chdir(hooks_path) do\n        Overcommit::Utils.supported_hook_types.each do |hook_type|\n          unless can_replace_file?(hook_type)\n            raise Overcommit::Exceptions::PreExistingHooks,\n                  \"Hook '#{File.expand_path(hook_type)}' already exists and \" \\\n                  'was not installed by Overcommit'\n          end\n          FileUtils.rm_f(hook_type)\n          FileUtils.cp('overcommit-hook', hook_type)\n        end\n      end\n    end\n\n    def can_replace_file?(file)\n      @options[:force] ||\n        !File.exist?(file) ||\n        overcommit_hook?(file)\n    end\n\n    def preserve_old_hooks\n      return unless File.directory?(hooks_path)\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/sds/overcommit/blob/fee0cd74b26eb81f64b43b7fab17bbb541575cc4/lib/overcommit/installer.rb#L97-L133","documentation":"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.","triggerScenarios":"'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.","commonSituations":"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.","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"],"exampleFix":"# before\n$ overcommit --install\nHook '/repo/.git/hooks/pre-commit' already exists and was not installed by Overcommit\n\n# after\n$ mv .git/hooks/pre-commit .git/hooks/pre-commit.bak\n$ overcommit --install","handlingStrategy":"validation","validationCode":"hooks_path = `git config core.hooksPath`.strip\nhooks_path = File.join(`git rev-parse --git-dir`.strip, 'hooks') if hooks_path.empty?\nforeign = Overcommit::Utils.supported_hook_types.select do |type|\n  f = File.join(hooks_path, type)\n  File.exist?(f) && File.read(f) !~ /overcommit/\nend\nabort \"Foreign hooks present: #{foreign.join(', ')} - back them up first\" unless foreign.empty?","typeGuard":"def foreign_hooks(hooks_path)\n  Overcommit::Utils.supported_hook_types.select do |type|\n    f = File.join(hooks_path, type)\n    File.exist?(f) && File.read(f) !~ /overcommit/\n  end\nend","tryCatchPattern":"begin\n  installer.run(target, action: :install)\nrescue Overcommit::Exceptions::PreExistingHooks => e\n  warn \"#{e.message} - back up the hook or re-run with --force\"\n  exit 1\nend","preventionTips":["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"],"tags":["git","git-hooks","overcommit","install","backup"],"backgroundTag":"git-hook-already-exists","analyzedSha":"fee0cd74b26eb81f64b43b7fab17bbb541575cc4","analyzedAt":"2026-08-23T04:07:28.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}