You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] watch rebuilds in an endless loop when the watched path contains .git #14362
With a rebuild watch rule whose path contains the repository's .git directory (for example path: . in a project at the repository root), a single source edit makes docker compose watch rebuild over and over: about 30 rebuilds in 30 seconds, and it never stops. An empty git commit starts the same loop. With a sync rule, git operations sync the .git contents into the container.
.git/ is meant to be always ignored (pkg/compose/watch.go adds a hardcoded .git/ ignore rule), but that rule never matches inside the project. Every build then feeds the loop: buildx reads the git state of the build context for provenance and updates .git while doing so, and watch sees that as a new change.
Expected: changes under .git/ are ignored, so one edit triggers one rebuild.
Workaround: add .git to .dockerignore, or set BUILDX_GIT_INFO=0.
Expected: changes under .git/ inside the watched path are ignored.
With nothing edited, the count stays at 0. With .git in .dockerignore or BUILDX_GIT_INFO=0, one edit gives 1.
Compose Version
Docker Compose version 5.0.1
Also reproduced on main (289d8a037).
buildx v0.30.1-desktop.1 (also v0.24.0)
Docker Environment
Docker Engine 29.1.3 (linux/arm64, Docker Desktop on macOS)
Anything else?
The rule is built with watch.NewDockerPatternMatcher("/", []string{".git/"}) in pkg/compose/watch.go (two places). Patterns are joined to the base path, so this becomes /.git/ and only matches a .git at the filesystem root. Events carry full paths such as /home/me/project/.git/index, so they never match.
With **/.git instead, a local build of main stops the loop: one edit gives 1 rebuild, an empty commit gives 0, and .git is no longer synced. **/.git matches .git and its contents at any depth, but not .gitignore or .github/.
#14217 changes the same ignore set (it excludes the Dockerfile and compose files) but does not touch .git.
changed the title [-][BUG] `watch` syncs `.git/` changes even though `.git` is meant to be ignored[/-][+][BUG] `watch` rebuilds in an endless loop when the watched path contains `.git`[/+]on Oct 19, 2026
A note on how this was found, in case it helps triage.
At first I thought this was only a missing filter: .git changes were not ignored, so watch would sync them or trigger an extra rebuild now and then. Wasteful, but harmless.
Looking further, I found a worse problem with the rebuild action. The extra rebuild does not stop at one. Each build makes buildx update .git while it reads the git state for provenance, watch picks that up as a new change, and the cycle repeats. So a single edit, or even an empty commit, never settles. Disabling buildx's git info (BUILDX_GIT_INFO=0) or ignoring .git stops it, which points to the unmatched .git/ rule as the root cause.
Activity
[-][BUG] `watch` syncs `.git/` changes even though `.git` is meant to be ignored[/-][+][BUG] `watch` rebuilds in an endless loop when the watched path contains `.git`[/+]htoyoda18 commentedon Oct 19, 2026
A note on how this was found, in case it helps triage.
At first I thought this was only a missing filter:
.gitchanges were not ignored, so watch would sync them or trigger an extra rebuild now and then. Wasteful, but harmless.Looking further, I found a worse problem with the
rebuildaction. The extra rebuild does not stop at one. Each build makes buildx update.gitwhile it reads the git state for provenance, watch picks that up as a new change, and the cycle repeats. So a single edit, or even an empty commit, never settles. Disabling buildx's git info (BUILDX_GIT_INFO=0) or ignoring.gitstops it, which points to the unmatched.git/rule as the root cause.