diff --git a/pygitweb/auth_test.py b/pygitweb/auth_test.py
index 9a24ae8..387396c 100644
--- a/pygitweb/auth_test.py
+++ b/pygitweb/auth_test.py
@@ -319,17 +319,17 @@ def test_oauth_callback_creates_session(client: TestClient, oauth_auth_config: A
 			params={"code": "auth-code", "state": "idp-state"},
 			follow_redirects=False,
 		)
-	assert r.status_code == 303
-	rec = get_session(r.cookies["pygitweb_access_token"])
-	assert rec is not None
-	assert rec.username == "user@example.com"
-	assert rec.subject == "oauth-sub-1"
-	assert rec.email == "user@example.com"
-	assert rec.auth_method == "oauth"
-	assert client.get("/users/me").json()["username"] == "user@example.com"
-	status = client.get("/auth/status").json()
-	assert status["username"] == "user@example.com"
-	assert status["gravatar_url"] == gravatar_url("user@example.com")
+		assert r.status_code == 303
+		rec = get_session(r.cookies["pygitweb_access_token"])
+		assert rec is not None
+		assert rec.username == "user@example.com"
+		assert rec.subject == "oauth-sub-1"
+		assert rec.email == "user@example.com"
+		assert rec.auth_method == "oauth"
+		assert client.get("/users/me").json()["username"] == "user@example.com"
+		status = client.get("/auth/status").json()
+		assert status["username"] == "user@example.com"
+		assert status["gravatar_url"] == gravatar_url("user@example.com")
 	clear_client_cookies(client)
 
 
diff --git a/pygitweb/hooks_install.py b/pygitweb/hooks_install.py
index e4ca029..e65b6b9 100644
--- a/pygitweb/hooks_install.py
+++ b/pygitweb/hooks_install.py
@@ -9,6 +9,7 @@ the repo (`<repo>/.git/hooks` for non-bare, `<repo>/hooks` for bare).
 
 from __future__ import annotations
 
+import hashlib
 import os
 import re
 import shutil
@@ -73,6 +74,19 @@ class InstalledHookInfo(TypedDict):
 	target: str
 	status: str
 	version: str | None
+	content_hash: str | None
+
+
+def content_hash(path: Path) -> str:
+	"""Return the SHA-256 hex digest of a hook file's contents."""
+	return hashlib.sha256(path.read_bytes()).hexdigest()
+
+
+def sample_content_hash(sample_name: str) -> str:
+	sample: HookSample | None = get_sample(sample_name)
+	if sample is None:
+		raise KeyError(f"Unknown hook sample: {sample_name}")
+	return content_hash(Path(sample["source"]))
 
 
 def read_hook_version(path: Path) -> str | None:
@@ -106,17 +120,29 @@ def list_installed_hooks(project: str) -> list[InstalledHookInfo]:
 		st: HookStatus = status(project, sample["name"])
 		if st == HookStatus.NOT_INSTALLED:
 			continue
+		if st == HookStatus.DIFFERENT:
+			owner: str | None = _installed_sample_for_target(project, sample["target"])
+			if owner is not None and owner != sample["name"]:
+				continue
+		target_path: Path = _target_path(project, sample)
 		version: str | None = None
 		if st == HookStatus.INSTALLED:
 			version = get_installed_version(project, sample["name"])
 		else:
-			version = read_hook_version(_target_path(project, sample))
+			version = read_hook_version(target_path)
+		installed_hash: str | None = None
+		if target_path.is_file():
+			try:
+				installed_hash = content_hash(target_path)
+			except OSError:
+				pass
 		installed.append({
 			"name": sample["name"],
 			"label": sample["label"],
 			"target": sample["target"],
 			"status": st.value,
 			"version": version,
+			"content_hash": installed_hash,
 		})
 	return installed
 
@@ -163,6 +189,26 @@ def _target_path(project: str, sample: HookSample) -> Path:
 	return _hooks_dir(project) / sample["target"]
 
 
+def _installed_sample_for_target(project: str, target: str) -> str | None:
+	"""Return the sample name whose content is installed at target, if any."""
+	target_path: Path = _hooks_dir(project) / target
+	if not target_path.is_file():
+		return None
+	try:
+		installed_hash: str = content_hash(target_path)
+	except OSError:
+		return None
+	for sample in list_samples():
+		if sample["target"] != target:
+			continue
+		try:
+			if content_hash(Path(sample["source"])) == installed_hash:
+				return sample["name"]
+		except OSError:
+			continue
+	return None
+
+
 def status(project: str, sample_name: str) -> HookStatus:
 	sample: HookSample | None = get_sample(sample_name)
 	if sample is None:
diff --git a/pygitweb/hooks_install_test.py b/pygitweb/hooks_install_test.py
index 0962837..238dd8f 100644
--- a/pygitweb/hooks_install_test.py
+++ b/pygitweb/hooks_install_test.py
@@ -13,6 +13,7 @@ from pygitweb.hooks_install import (
 	HOOK_BUNDLES,
 	HookStatus,
 	bundle_status,
+	content_hash,
 	get_bundle,
 	get_installed_version,
 	get_sample,
@@ -26,6 +27,7 @@ from pygitweb.hooks_install import (
 	read_hook_version,
 	remove,
 	remove_bundle,
+	sample_content_hash,
 	status,
 )
 from pygitweb.main import app
@@ -337,10 +339,28 @@ class TestHookVersion:
 		assert get_installed_version(project_env["project"], "post-receive.notify") == "1"
 
 	def test_list_installed_hooks_includes_only_present_hooks(self, project_env: dict[str, str]) -> None:
+		notify_sample = get_sample("post-commit.notify")
+		push_sample = get_sample("post-commit.push-remotes")
+		assert notify_sample is not None
+		assert push_sample is not None
+		notify_hash = sample_content_hash("post-commit.notify")
+		push_hash = sample_content_hash("post-commit.push-remotes")
+		assert notify_hash != push_hash
+		assert content_hash(Path(notify_sample["source"])) == notify_hash
+		assert content_hash(Path(push_sample["source"])) == push_hash
+
 		install(project_env["project"], "post-commit.notify")
 		installed = list_installed_hooks(project_env["project"])
 		assert {entry["name"] for entry in installed} == {"post-commit.notify"}
 		assert installed[0]["version"] == "1"
+		assert installed[0]["content_hash"] == notify_hash
+
+		remove(project_env["project"], "post-commit.notify")
+		install(project_env["project"], "post-commit.push-remotes")
+		installed = list_installed_hooks(project_env["project"])
+		assert {entry["name"] for entry in installed} == {"post-commit.push-remotes"}
+		assert installed[0]["version"] == "1"
+		assert installed[0]["content_hash"] == push_hash
 
 	def test_list_installable_hooks_excludes_installed(self, project_env: dict[str, str]) -> None:
 		install(project_env["project"], "post-commit.notify")
