diff --git a/gitplusplus.cpp b/gitplusplus.cpp index 273ec96..bfd174b 100644 --- a/gitplusplus.cpp +++ b/gitplusplus.cpp @@ -515,8 +515,7 @@ void GitPlusPlusView::setupFileWatcher() delete m_watcher; m_watcher = new QFileSystemWatcher(this); - // Watch .git/index (changes on stage/unstage/commit/pull/merge) - // and .git/HEAD (changes on branch switch) + // Determine the actual .git directory // For worktrees, .git is a file pointing to the real git dir QString gitDir; QString dotGit = m_gitDir + QStringLiteral("/.git"); @@ -536,24 +535,36 @@ void GitPlusPlusView::setupFileWatcher() if (gitDir.isEmpty()) return; + // Watch the git directory itself — picks up renames of index, HEAD, refs, etc. + // This is more robust than watching individual files which get replaced atomically. QStringList watchPaths; + watchPaths << gitDir; + + // Also watch refs/heads for branch changes + QString refsHeads = gitDir + QStringLiteral("/refs/heads"); + if (QFileInfo::exists(refsHeads)) + watchPaths << refsHeads; + + m_watcher->addPaths(watchPaths); + connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) { + m_fsDebounce.start(); + }); + // Still watch individual files as a fallback for systems where dir watching is coarse QString indexFile = gitDir + QStringLiteral("/index"); QString headFile = gitDir + QStringLiteral("/HEAD"); - if (QFileInfo::exists(indexFile)) watchPaths << indexFile; - if (QFileInfo::exists(headFile)) watchPaths << headFile; - - if (!watchPaths.isEmpty()) { - m_watcher->addPaths(watchPaths); + QStringList filePaths; + if (QFileInfo::exists(indexFile)) filePaths << indexFile; + if (QFileInfo::exists(headFile)) filePaths << headFile; + if (!filePaths.isEmpty()) { + m_watcher->addPaths(filePaths); connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) { - // Re-add the path: QFileSystemWatcher drops watches when files are - // replaced atomically (git writes a temp file then renames over it) + // Re-add: atomic renames remove the watch if (!m_watcher->files().contains(path)) { - QTimer::singleShot(100, this, [this, path]() { - if (QFileInfo::exists(path)) + QTimer::singleShot(200, this, [this, path]() { + if (QFileInfo::exists(path) && m_watcher) m_watcher->addPath(path); }); } - // Debounce: multiple changes can fire rapidly m_fsDebounce.start(); }); }