diff --git a/pygittools/src/pygittools/tui/app.py b/pygittools/src/pygittools/tui/app.py
index 3ebc119..7fae440 100644
--- a/pygittools/src/pygittools/tui/app.py
+++ b/pygittools/src/pygittools/tui/app.py
@@ -106,5 +106,13 @@ def _apply_result(
 
 	if result.switch_repo is not None and ctx is not None and stack:
 		stack[-1].on_enter(ctx)
+	elif (
+		result.repo_changed
+		and result.action == PageAction.POP
+		and ctx is not None
+		and stack
+		and isinstance(stack[-1], HomePage)
+	):
+		stack[-1].refresh()
 
 	return ctx, stack
diff --git a/pygittools/src/pygittools/tui/app_test.py b/pygittools/src/pygittools/tui/app_test.py
index 141d3ea..67a0204 100644
--- a/pygittools/src/pygittools/tui/app_test.py
+++ b/pygittools/src/pygittools/tui/app_test.py
@@ -56,6 +56,30 @@ def test_apply_result_push_and_pop(page_ctx: PageContext) -> None:
 	assert len(stack) == 1
 
 
+def test_apply_result_pop_repo_changed_refreshes_home(page_ctx: PageContext) -> None:
+	home = home_page()
+	home.on_enter(page_ctx)
+	overlay = NoRepoPage(Path("/tmp"))
+	with patch.object(home, "refresh") as refresh:
+		ctx, stack = _apply_result(
+			[home, overlay],
+			page_ctx,
+			PageResult(action=PageAction.POP, repo_changed=True),
+		)
+	assert ctx is page_ctx
+	assert stack == [home]
+	refresh.assert_called_once_with()
+
+
+def test_apply_result_pop_without_repo_change_skips_refresh(page_ctx: PageContext) -> None:
+	home = home_page()
+	home.on_enter(page_ctx)
+	overlay = NoRepoPage(Path("/tmp"))
+	with patch.object(home, "refresh") as refresh:
+		_apply_result([home, overlay], page_ctx, PageResult(action=PageAction.POP))
+	refresh.assert_not_called()
+
+
 def test_apply_result_pop_keeps_root(page_ctx: PageContext) -> None:
 	home = home_page()
 	ctx, stack = _apply_result([home], page_ctx, PageResult(action=PageAction.POP))
diff --git a/pygittools/src/pygittools/tui/changes_list.py b/pygittools/src/pygittools/tui/changes_list.py
index 00364fa..b8bffba 100644
--- a/pygittools/src/pygittools/tui/changes_list.py
+++ b/pygittools/src/pygittools/tui/changes_list.py
@@ -63,12 +63,14 @@ class _Row:
 class NavKeyResult:
 	enter_input: bool = False
 	layout_changed: bool = False
+	committed: bool = False
 
 
 @dataclass(frozen=True, slots=True)
 class InputKeyResult:
 	layout_changed: bool = False
 	relinquish: bool = False
+	committed: bool = False
 
 
 _SECTION_ORDER: tuple[tuple[SectionId, str], ...] = (
@@ -81,6 +83,7 @@ _SECTION_ORDER: tuple[tuple[SectionId, str], ...] = (
 class ChangesList:
 	def __init__(self) -> None:
 		self._collapsed: dict[SectionId, bool] = dict.fromkeys(SectionId, False)
+		self._files: dict[SectionId, list[str]] = {section: [] for section in SectionId}
 		self._rows: list[_Row] = []
 		self._list_state = ListState()
 		self._commit_state = TextState()
@@ -102,17 +105,20 @@ class ChangesList:
 
 	def refresh(self, repo: Repository) -> None:
 		staged, unstaged, untracked = categorize_status(repo)
-		self._staged_count = len(staged)
-		files_by_section = {
+		self._files = {
 			SectionId.STAGED: staged,
 			SectionId.UNSTAGED: unstaged,
 			SectionId.UNTRACKED: untracked,
 		}
+		self._staged_count = len(staged)
+		self._rebuild_rows()
+
+	def _rebuild_rows(self) -> None:
 		rows: list[_Row] = [
 			_Row(kind="commit", section=None, path=None, label=self._commit_label()),
 		]
 		for section_id, title in _SECTION_ORDER:
-			files = files_by_section[section_id]
+			files = self._files[section_id]
 			marker = ">" if self._collapsed[section_id] else "v"
 			rows.append(
 				_Row(
@@ -214,12 +220,11 @@ class ChangesList:
 				return NavKeyResult(enter_input=True)
 			if self._try_begin_input(key):
 				return NavKeyResult(enter_input=True)
-			layout_changed = self._handle_commit_nav_key(key, repo)
-			return NavKeyResult(layout_changed=layout_changed)
+			return self._handle_commit_nav_key(key, repo)
 
 		if (is_left(key) or is_right(key) or is_space(key)) and row.kind == "header" and row.section is not None:
 			self._collapsed[row.section] = not self._collapsed[row.section]
-			self.refresh(repo)
+			self._rebuild_rows()
 			return NavKeyResult(layout_changed=True)
 		if is_enter(key) and row.kind == "header" and row.section is not None:
 			self._toggle_section(repo, row.section)
@@ -241,7 +246,7 @@ class ChangesList:
 				self.persist_commit_draft(repo)
 				self._error = None
 				self.refresh(repo)
-				return InputKeyResult(layout_changed=True, relinquish=True)
+				return InputKeyResult(layout_changed=True, relinquish=True, committed=True)
 			self._error = error
 			return InputKeyResult()
 		self._commit_state.focus()
@@ -281,7 +286,7 @@ class ChangesList:
 			return True
 		return False
 
-	def _handle_commit_nav_key(self, key: KeyLike, repo: Repository) -> bool:
+	def _handle_commit_nav_key(self, key: KeyLike, repo: Repository) -> NavKeyResult:
 		if is_enter(key):
 			ok, error = commit_staged(repo, self.commit_message)
 			if ok:
@@ -289,9 +294,9 @@ class ChangesList:
 				self.persist_commit_draft(repo)
 				self._error = None
 				self.refresh(repo)
-				return True
+				return NavKeyResult(layout_changed=True, committed=True)
 			self._error = error
-		return False
+		return NavKeyResult()
 
 	def _commit_label(self) -> str:
 		return f"Commit: {self.commit_message}"
@@ -303,17 +308,11 @@ class ChangesList:
 			stage_path(repo, path)
 
 	def _toggle_section(self, repo: Repository, section: SectionId) -> None:
-		staged, unstaged, untracked = categorize_status(repo)
-		paths_by_section = {
-			SectionId.STAGED: staged,
-			SectionId.UNSTAGED: unstaged,
-			SectionId.UNTRACKED: untracked,
-		}
-		paths = paths_by_section[section]
+		paths = self._files[section]
 		if section == SectionId.STAGED:
 			if paths:
 				unstage_paths(repo, paths)
 			else:
-				stage_paths(repo, unstaged + untracked)
+				stage_paths(repo, self._files[SectionId.UNSTAGED] + self._files[SectionId.UNTRACKED])
 		else:
 			stage_paths(repo, paths)
diff --git a/pygittools/src/pygittools/tui/changes_list_test.py b/pygittools/src/pygittools/tui/changes_list_test.py
index c62acae..925f986 100644
--- a/pygittools/src/pygittools/tui/changes_list_test.py
+++ b/pygittools/src/pygittools/tui/changes_list_test.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 from pathlib import Path
-from unittest.mock import MagicMock
+from unittest.mock import MagicMock, patch
 
 import pytest
 from pygit2 import Repository
@@ -69,6 +69,19 @@ def test_collapse_section_with_space(committed_repo: Repository) -> None:
 	assert result.layout_changed is True
 
 
+def test_collapse_does_not_reread_status(committed_repo: Repository) -> None:
+	changes = ChangesList()
+	changes.refresh(committed_repo)
+	for index, row in enumerate(changes._rows):
+		if row.kind == "header":
+			changes._list_state.select(index)
+			break
+	with patch("pygittools.tui.changes_list.categorize_status") as status:
+		changes.handle_nav_key(key(" "), committed_repo)
+	status.assert_not_called()
+	assert any(row.kind == "header" and row.label.startswith("[>") for row in changes._rows)
+
+
 def test_commit_input_flow(committed_repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
 	(Path(committed_repo.workdir) / "new.txt").write_text("x\n", encoding="utf-8")
 	committed_repo.index.add("new.txt")
@@ -94,6 +107,7 @@ def test_commit_enter_with_message(committed_repo: Repository, monkeypatch: pyte
 	)
 	result = changes.handle_nav_key(key("Enter"), committed_repo)
 	assert result.layout_changed is True
+	assert result.committed is True
 
 
 def test_commit_enter_failure(committed_repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
diff --git a/pygittools/src/pygittools/tui/input_context.py b/pygittools/src/pygittools/tui/input_context.py
index ecdce9a..c1a3015 100644
--- a/pygittools/src/pygittools/tui/input_context.py
+++ b/pygittools/src/pygittools/tui/input_context.py
@@ -27,6 +27,7 @@ _HomeTab = Literal["status", "log", "tasks", "worktrees"]
 class ContextDispatch:
 	page_result: PageResult | None = None
 	next_mode: Literal["nav", "input"] | None = None
+	refresh_log: bool = False
 
 
 class PageInputHost(Protocol):
@@ -143,7 +144,7 @@ class NavContext:
 		nav_result = host.changes.handle_nav_key(key, ctx.repo)
 		if nav_result.enter_input:
 			return ContextDispatch(next_mode="input")
-		return ContextDispatch()
+		return ContextDispatch(refresh_log=nav_result.committed)
 
 
 class InputContext:
@@ -158,7 +159,7 @@ class InputContext:
 		if ctx is not None:
 			result = host.changes.handle_input_key(key, ctx.repo)
 			if result.relinquish:
-				return ContextDispatch(next_mode="nav")
+				return ContextDispatch(next_mode="nav", refresh_log=result.committed)
 		return ContextDispatch()
 
 
diff --git a/pygittools/src/pygittools/tui/log_list.py b/pygittools/src/pygittools/tui/log_list.py
index efec6de..762aeda 100644
--- a/pygittools/src/pygittools/tui/log_list.py
+++ b/pygittools/src/pygittools/tui/log_list.py
@@ -69,6 +69,7 @@ class CommitLogList:
 		)
 
 	def handle_nav_key(self, key: KeyLike, repo: Repository) -> LogNavKeyResult:
+		del repo
 		if is_up(key):
 			selected = self._list_state.selected or 0
 			self._list_state.select(max(0, selected - 1))
@@ -77,7 +78,6 @@ class CommitLogList:
 			selected = self._list_state.selected or 0
 			self._list_state.select(min(max(0, len(self._entries) - 1), selected + 1))
 			return LogNavKeyResult()
-		self.refresh(repo)
 		return LogNavKeyResult()
 
 	def status_hint(self) -> str:
diff --git a/pygittools/src/pygittools/tui/log_list_test.py b/pygittools/src/pygittools/tui/log_list_test.py
index 28e8243..53f6158 100644
--- a/pygittools/src/pygittools/tui/log_list_test.py
+++ b/pygittools/src/pygittools/tui/log_list_test.py
@@ -4,7 +4,7 @@ from __future__ import annotations
 
 import json
 from pathlib import Path
-from unittest.mock import MagicMock
+from unittest.mock import MagicMock, patch
 
 import pygit2
 import pytest
@@ -61,7 +61,9 @@ def test_commit_log_list_navigation(tmp_path: Path) -> None:
 	log.refresh(repo)
 	log.handle_nav_key(key("Down"), repo)
 	log.handle_nav_key(key("Up"), repo)
-	log.handle_nav_key(key("x"), repo)
+	with patch.object(log, "refresh") as refresh:
+		log.handle_nav_key(key("x"), repo)
+	refresh.assert_not_called()
 
 
 def test_load_entries_without_head(repo: pygit2.Repository) -> None:
diff --git a/pygittools/src/pygittools/tui/pages/branches.py b/pygittools/src/pygittools/tui/pages/branches.py
index a155a5a..f208ac5 100644
--- a/pygittools/src/pygittools/tui/pages/branches.py
+++ b/pygittools/src/pygittools/tui/pages/branches.py
@@ -132,7 +132,7 @@ class BranchPickerPage:
 			branch = self._filtered[self._list_state.selected or 0]
 			ok, error = checkout_branch(ctx.repo, branch)
 			if ok:
-				return PageResult(action=PageAction.POP)
+				return PageResult(action=PageAction.POP, repo_changed=True)
 			self._error = error
 			return PageResult()
 		# Typing jumps back to filter.
@@ -145,7 +145,7 @@ class BranchPickerPage:
 	def _try_create_branch(self, ctx: PageContext) -> PageResult:
 		ok, error = create_branch_from_current(ctx.repo, self._filter_state.value())
 		if ok:
-			return PageResult(action=PageAction.POP)
+			return PageResult(action=PageAction.POP, repo_changed=True)
 		self._error = error
 		return PageResult()
 
diff --git a/pygittools/src/pygittools/tui/pages/home.py b/pygittools/src/pygittools/tui/pages/home.py
index ac1ed0d..d4d34e1 100644
--- a/pygittools/src/pygittools/tui/pages/home.py
+++ b/pygittools/src/pygittools/tui/pages/home.py
@@ -87,6 +87,9 @@ class HomePage:
 			if self._header_focus == "actions":
 				self._header_focus = "changes"
 
+	def refresh(self) -> None:
+		self._refresh()
+
 	def _refresh(self) -> None:
 		ctx = self._ctx
 		if ctx is None:
@@ -188,7 +191,8 @@ class HomePage:
 			self._input_mode = input_context()
 		elif dispatch.next_mode == "nav":
 			self._input_mode = nav_context()
-		self._refresh()
+		if dispatch.refresh_log and self._ctx is not None:
+			self._log.refresh(self._ctx.repo)
 		if dispatch.page_result is not None:
 			return dispatch.page_result
 		return PageResult()
diff --git a/pygittools/src/pygittools/tui/pages/task_editor.py b/pygittools/src/pygittools/tui/pages/task_editor.py
index 7d5a889..5b7d99c 100644
--- a/pygittools/src/pygittools/tui/pages/task_editor.py
+++ b/pygittools/src/pygittools/tui/pages/task_editor.py
@@ -285,7 +285,7 @@ class TaskEditorPage:
 			except Exception as exc:  # noqa: BLE001
 				self._error = str(exc)
 				return PageResult()
-			return PageResult(action=PageAction.POP)
+			return PageResult(action=PageAction.POP, repo_changed=True)
 
 		task = get_task(ctx.repo, self._task_ref)
 		if task is None:
@@ -299,14 +299,14 @@ class TaskEditorPage:
 		task.due_date = due_dt
 		task.update_message()
 		task.write(ctx.repo)
-		return PageResult(action=PageAction.POP)
+		return PageResult(action=PageAction.POP, repo_changed=True)
 
 	def _delete_local(self) -> PageResult:
 		ctx = self._ctx
 		if ctx is None or self._task_ref is None:
 			return PageResult(action=PageAction.POP)
 		delete_task_local(ctx.repo, self._task_ref)
-		return PageResult(action=PageAction.POP)
+		return PageResult(action=PageAction.POP, repo_changed=True)
 
 	def _delete_remote_local(self) -> PageResult:
 		ctx = self._ctx
@@ -319,7 +319,7 @@ class TaskEditorPage:
 		delete_task_local(ctx.repo, self._task_ref)
 		if remote_name is not None:
 			push_board_tags(ctx.repo, remote_name, self._board_name)
-		return PageResult(action=PageAction.POP)
+		return PageResult(action=PageAction.POP, repo_changed=True)
 
 
 def _replace_state_field(state: _EditorState, field: _FieldName, value: str) -> _EditorState:
diff --git a/pygittools/src/pygittools/tui/pages/worktree_add.py b/pygittools/src/pygittools/tui/pages/worktree_add.py
index b884dad..ea5b61d 100644
--- a/pygittools/src/pygittools/tui/pages/worktree_add.py
+++ b/pygittools/src/pygittools/tui/pages/worktree_add.py
@@ -111,7 +111,7 @@ class WorktreeAddPage:
 		branch = self._branch_state.value().strip() or None
 		ok, error = add_worktree(ctx.repo, Path(raw_path), branch)
 		if ok:
-			return PageResult(action=PageAction.POP)
+			return PageResult(action=PageAction.POP, repo_changed=True)
 		self._error = error
 		return PageResult()
 
diff --git a/pygittools/src/pygittools/tui/pages_test.py b/pygittools/src/pygittools/tui/pages_test.py
index d4b4ec5..19904e4 100644
--- a/pygittools/src/pygittools/tui/pages_test.py
+++ b/pygittools/src/pygittools/tui/pages_test.py
@@ -66,7 +66,7 @@ def test_home_page_idle_refresh_after_interval(page_ctx: PageContext) -> None:
 	worktrees_refresh.assert_called_once_with(page_ctx.repo)
 
 
-def test_home_page_handle_key_refreshes(page_ctx: PageContext) -> None:
+def test_home_page_handle_key_skips_refresh(page_ctx: PageContext) -> None:
 	page = HomePage()
 	page.on_enter(page_ctx)
 	with (
@@ -76,10 +76,68 @@ def test_home_page_handle_key_refreshes(page_ctx: PageContext) -> None:
 		patch.object(page.worktrees, "refresh") as worktrees_refresh,
 	):
 		page.handle_key(key("j"))
-	changes_refresh.assert_called_once_with(page_ctx.repo)
-	log_refresh.assert_called_once_with(page_ctx.repo)
-	tasks_refresh.assert_called_once_with(page_ctx.repo)
-	worktrees_refresh.assert_called_once_with(page_ctx.repo)
+	changes_refresh.assert_not_called()
+	log_refresh.assert_not_called()
+	tasks_refresh.assert_not_called()
+	worktrees_refresh.assert_not_called()
+
+
+def test_home_page_commit_typing_skips_refresh(page_ctx: PageContext) -> None:
+	page = HomePage()
+	page.on_enter(page_ctx)
+	page.handle_key(key("a"))
+	with (
+		patch.object(page.changes, "refresh") as changes_refresh,
+		patch.object(page.log, "refresh") as log_refresh,
+		patch.object(page.tasks, "refresh") as tasks_refresh,
+		patch.object(page.worktrees, "refresh") as worktrees_refresh,
+	):
+		page.handle_key(key("b"))
+	changes_refresh.assert_not_called()
+	log_refresh.assert_not_called()
+	tasks_refresh.assert_not_called()
+	worktrees_refresh.assert_not_called()
+	assert page.changes.commit_message == "ab"
+
+
+def test_home_page_commit_refreshes_log(committed_repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
+	monkeypatch.setattr(
+		"pygittools.tui.changes_list.commit_staged",
+		lambda _repo, _msg: (True, ""),
+	)
+	ctx = PageContext(repo=committed_repo, repo_path=Path(committed_repo.path))
+	page = HomePage()
+	page.on_enter(ctx)
+	page.changes.set_commit_message("amend note")
+	with (
+		patch.object(page.log, "refresh") as log_refresh,
+		patch.object(page.tasks, "refresh") as tasks_refresh,
+		patch.object(page.worktrees, "refresh") as worktrees_refresh,
+	):
+		page.handle_key(key("Enter"))
+	log_refresh.assert_called_once_with(committed_repo)
+	tasks_refresh.assert_not_called()
+	worktrees_refresh.assert_not_called()
+
+
+def test_home_page_input_commit_refreshes_log(committed_repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
+	monkeypatch.setattr(
+		"pygittools.tui.changes_list.commit_staged",
+		lambda _repo, _msg: (True, ""),
+	)
+	ctx = PageContext(repo=committed_repo, repo_path=Path(committed_repo.path))
+	page = HomePage()
+	page.on_enter(ctx)
+	page.handle_key(key("m"))
+	with (
+		patch.object(page.log, "refresh") as log_refresh,
+		patch.object(page.tasks, "refresh") as tasks_refresh,
+		patch.object(page.worktrees, "refresh") as worktrees_refresh,
+	):
+		page.handle_key(key("Enter"))
+	log_refresh.assert_called_once_with(committed_repo)
+	tasks_refresh.assert_not_called()
+	worktrees_refresh.assert_not_called()
 
 
 def test_home_page_draw_and_tabs(committed_repo: Repository) -> None:
@@ -225,6 +283,7 @@ def test_empty_repo_can_create_branch_and_commit(repo: Repository) -> None:
 	workdir = repo.workdir
 	assert workdir is not None
 	(Path(workdir) / "hello.txt").write_text("hello\n", encoding="utf-8")
+	page.refresh()
 	page.draw(MagicMock(), Rect(0, 0, 80, 20))
 	page.handle_key(key("Down"))
 	_press_until(page, key("Down"), lambda hint: hint.startswith("Enter stage —"))
diff --git a/pygittools/src/pygittools/tui/tasks_list.py b/pygittools/src/pygittools/tui/tasks_list.py
index 5f4f2aa..8c64148 100644
--- a/pygittools/src/pygittools/tui/tasks_list.py
+++ b/pygittools/src/pygittools/tui/tasks_list.py
@@ -9,7 +9,13 @@ from pygit2 import Repository
 from pyratatui import Frame, List, ListItem, ListState, Rect
 
 from pygittools.tags_sync import format_sync_result, sync_board_tags
-from pygittools.tasks_query import BOARD_STATUS_ORDER, BoardView, get_board_tasks_grouped, list_boards
+from pygittools.tasks_query import (
+	BOARD_STATUS_ORDER,
+	BoardColumnView,
+	BoardView,
+	get_board_tasks_grouped,
+	list_boards,
+)
 from pygittools.tui.git_colors import current_theme, focus_style
 from pygittools.tui.keys import KeyLike, is_down, is_enter, is_left, is_right, is_space, is_up
 from pygittools.tui.types import PageAction, PageResult
@@ -28,6 +34,7 @@ class TasksBoardList:
 		self._boards: list[BoardView] = []
 		self._board_index = 0
 		self._board_name: str | None = None
+		self._columns: list[BoardColumnView] = []
 		self._collapsed: dict[str, bool] = {status: False for status in BOARD_STATUS_ORDER}
 		self._rows: list[_Row] = []
 		self._list_state = ListState()
@@ -43,6 +50,7 @@ class TasksBoardList:
 	def refresh(self, repo: Repository) -> None:
 		self._boards = list_boards(repo)
 		if not self._boards:
+			self._columns = []
 			self._rows = []
 			self._board_name = None
 			self._list_state.select(0)
@@ -55,21 +63,29 @@ class TasksBoardList:
 		self._board_index = max(0, min(self._board_index, len(self._boards) - 1))
 		self._board_name = self._boards[self._board_index]["name"]
 
-		rows: list[_Row] = []
-		board = self._boards[self._board_index]
-		board_label = f"Board: {board['name']} ({board['task_count']} tasks)"
-		rows.append(_Row(kind="board", status=None, task_ref=None, label=board_label))
-
 		try:
-			columns = get_board_tasks_grouped(repo, self._board_name or "")
+			self._columns = get_board_tasks_grouped(repo, self._board_name or "")
 		except KeyError as exc:
 			self._error = str(exc)
-			self._rows = rows
-			selected = self._list_state.selected or 0
-			self._list_state.select(min(selected, max(0, len(self._rows) - 1)))
+			self._columns = []
+		self._rebuild_rows()
+
+	def _rebuild_rows(self) -> None:
+		if not self._boards:
+			self._rows = []
+			self._list_state.select(0)
 			return
 
-		for column in columns:
+		board = self._boards[self._board_index]
+		rows: list[_Row] = [
+			_Row(
+				kind="board",
+				status=None,
+				task_ref=None,
+				label=f"Board: {board['name']} ({board['task_count']} tasks)",
+			),
+		]
+		for column in self._columns:
 			status = column["status"]
 			label = column["label"]
 			tasks = column["tasks"]
@@ -190,7 +206,7 @@ class TasksBoardList:
 		if row.kind == "status_header" and row.status is not None:
 			if is_left(key) or is_right(key) or is_space(key) or is_enter(key):
 				self._collapsed[row.status] = not self._collapsed.get(row.status, False)
-				self.refresh(repo)
+				self._rebuild_rows()
 			return None
 
 		if is_enter(key):
diff --git a/pygittools/src/pygittools/tui/tasks_list_test.py b/pygittools/src/pygittools/tui/tasks_list_test.py
index 8468aad..0e5bf81 100644
--- a/pygittools/src/pygittools/tui/tasks_list_test.py
+++ b/pygittools/src/pygittools/tui/tasks_list_test.py
@@ -1,10 +1,12 @@
 from __future__ import annotations
 
-from unittest.mock import MagicMock
+from unittest.mock import MagicMock, patch
 
 from pyratatui import Rect
 
+from pygittools.tui.keys import key
 from pygittools.tui.tasks_list import TasksBoardList, _Row
+from pygittools.tui.types import PageContext
 
 
 def test_draw_error_offsets_list_selection() -> None:
@@ -21,3 +23,28 @@ def test_draw_error_offsets_list_selection() -> None:
 	list_state = frame.render_stateful_list.call_args.args[2]
 	assert list_state.selected == 1
 	assert (tasks._list_state.selected or 0) == 0
+
+
+def test_collapse_rebuilds_without_git(page_ctx: PageContext) -> None:
+	tasks = TasksBoardList()
+	tasks._boards = [{"name": "Tasks", "description": "", "task_count": 1}]
+	tasks._board_index = 0
+	tasks._board_name = "Tasks"
+	tasks._columns = [
+		{
+			"status": "TODO",
+			"label": "Todo",
+			"tasks": [{"title": "one", "ref": "refs/tasks/one"}],
+		},
+	]
+	tasks._rebuild_rows()
+	header = next(index for index, row in enumerate(tasks._rows) if row.kind == "status_header")
+	tasks._list_state.select(header)
+	with (
+		patch("pygittools.tui.tasks_list.list_boards") as list_boards,
+		patch("pygittools.tui.tasks_list.get_board_tasks_grouped") as grouped,
+	):
+		tasks.handle_nav_key(key(" "), page_ctx.repo)
+	list_boards.assert_not_called()
+	grouped.assert_not_called()
+	assert all(row.kind != "task" for row in tasks._rows)
diff --git a/pygittools/src/pygittools/tui/types.py b/pygittools/src/pygittools/tui/types.py
index b458438..e6aa7aa 100644
--- a/pygittools/src/pygittools/tui/types.py
+++ b/pygittools/src/pygittools/tui/types.py
@@ -26,6 +26,7 @@ class PageResult:
 	action: PageAction = PageAction.NONE
 	next_page: Page | None = None
 	switch_repo: Path | None = None
+	repo_changed: bool = False
 
 
 @dataclass(frozen=True, slots=True)
