Skip to content

dolt rm --cached <table> rejects unstaged changes; git rm --cached does not #10987

@aspiers

Description

@aspiers

Summary

dolt rm --cached api_keys fails with error: the table(s) api_keys have unstaged changes. when the working copy of api_keys differs from HEAD.

The Git equivalent — git rm --cached <path> — succeeds in the same situation: it removes the path from the index while leaving the modified working-copy content untouched.

Per @timsehn on Discord: "If it does not work the same way you would get it in git it is a bug and we'll fix it." Filing accordingly.

Versions

  • dolt version 1.86.6
  • git version (any modern; behaviour stable since long ago)

Use case

A table was accidentally committed (e.g. api_keys containing secrets). The user wants to:

  1. Stop tracking the table in Dolt (untrack from index / future commits).
  2. Keep the table in the working database (it is in active use).
  3. Add it to dolt_ignore so subsequent diffs/commits exclude it.

In Git this is the standard git rm --cached path && echo path >> .gitignore flow. In Dolt the equivalent first step fails whenever the table has any uncommitted modification, which is exactly the common case (the reason the user wants to untrack it is usually that it keeps changing).

Minimal repro — Dolt (fails)

$ mkdir dolt-repro && cd dolt-repro
$ dolt init --name=Repro --email=repro@example.com
Successfully initialized dolt data repository.

$ dolt sql -q "CREATE TABLE api_keys (id INT PRIMARY KEY, token VARCHAR(64));
                INSERT INTO api_keys VALUES (1, 'initial');"
$ dolt add api_keys
$ dolt commit -m "add api_keys"

# Make an unstaged change to the working copy
$ dolt sql -q "INSERT INTO api_keys VALUES (2, 'unstaged-change');"

$ dolt status
On branch main
Changes not staged for commit:
  (use "dolt add <table>" to update what will be committed)
  (use "dolt checkout <table>" to discard changes in working directory)
        modified:         api_keys

$ dolt rm --cached api_keys
error: the table(s) api_keys have unstaged changes.
$ echo $?
1

Minimal repro — Git (succeeds)

$ mkdir git-repro && cd git-repro
$ git init -q
$ printf 'token=initial\n' > api_keys
$ git add api_keys
$ git commit -q -m "add api_keys"

# Make an unstaged change to the working copy
$ printf 'token=unstaged-change\n' > api_keys

$ git status --short
 M api_keys

$ git rm --cached api_keys
rm 'api_keys'
$ echo $?
0

$ git status --short
D  api_keys
?? api_keys

$ cat api_keys
token=unstaged-change

Git removes the path from the index (staged deletion) while leaving the unstaged modified content on disk as an untracked file. No data loss; no requirement that the working copy match HEAD.

Expected behaviour in Dolt

dolt rm --cached api_keys should succeed regardless of whether the working table differs from HEAD:

  • Stage a deletion of api_keys from the index (so the next commit drops the table from version control).
  • Leave the working-copy table data intact in the database, so reads/writes against api_keys continue to work.

This matches git rm --cached's contract: "remove from the index only; do not touch the working tree."

Actual behaviour

dolt rm --cached refuses whenever the table has unstaged changes, forcing the user to either:

  • dolt checkout api_keys first (discards the live data — unacceptable for a table in active use), or
  • dolt add api_keys && dolt commit first (commits the very secrets the user is trying to stop tracking), or
  • work around it via dolt_ignore plus manual index manipulation.

None of these are equivalent to git rm --cached.

Related

  • dolt_ignore exists for preventing future tracking, but does not help with a table already in HEAD.
  • The error message itself implies the check is intentional — but it diverges from Git's contract for the same flag.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions