git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 2/2] mv: check for missing destination directory before renaming

From
Lucas Zamboni Orioli <lucaszam0@gmail.com>
Date
Jul 26, 2026, 17:59 UTC
Message-ID
<CAH01Q-_k1QEcTLTMygBceUWjGNFLNewixf80bYOD2_s20jajrQ@mail.gmail.com>
In-Reply-To
<xmqqik61yeyn.fsf@gitster.g>

Em dom., 26 de jul. de 2026 às 11:59, Junio C Hamano <gitster@pobox.com> escreveu:

> Think carefully about cases where 'a' is a directory and 'a/b' is a
> symlink, or where 'a' and 'a/b' are directories and 'a/b/c' is a
> symlink, and so on.  We do not want to craft an arbitrary rule that
> says we allow or refuse to operate depending on the link target.

Thanks for pushing on this, chasing the symlink case down turned up more than a bad message. With a tracked symlink in the leading path, "git mv" leaves the index inconsistent with the worktree:

    mkdir repo && cd repo
    git init
    echo content >a
    mkdir real-dir
    echo content >real-dir/b
    ln -s . c
    git add .
    git commit -m "initial"
    git mv a c/real-dir/a
    git status

'c' is a tracked symlink to '.'. The move follows it, so on disk the file lands at the resolved path 'real-dir/a', but the index records the literal 'c/real-dir/a'. "git status" then reports a staged rename to 'c/real-dir/a', an unstaged deletion of that same path (nothing is there on disk), and the real file untracked at 'real-dir/a', with the symlink 'c' also shown untracked. A later "git add" did reconcile it by finding the file at its real location, but "git mv" on its own has already produced an index that describes a worktree that doesn't exist, it got there precisely by traversing a tracked symlink.

So this is the "not careful enough" case you suspected, and the fix is the behavior you described: refuse to operate when any component of the destination's leading path is a symlink, independent of where it points. I'm thinking of using has_symlink_leading_path() (symlinks.c) for that check, which is what "git apply" already uses to avoid following in-tree symlinks, so the behavior stays consistent with the rest of the tree.

For v3 I'll fold this into the series: the leading-directory check will reject a missing directory or a non-directory/symlink component up front, which covers both the original misleading-error case and this symlink traversal. Tests will cover a symlink as the final component and as an intermediate one ('a/b/c' with 'a' a symlink), plus the existing missing-directory and dry-run cases.

Previous: Junio C HamanoNext: Lucas Zamboni Orioli via GitGitGadget
Message 14 of 28 in “mv: report missing destination leading directory”
  1. mv: report missing destination leading directoryLucas Zamboni Orioli via GitGitGadget, Jul 15, 2026
  2. Ben KnobleJul 15, 2026
  3. Lucas Zamboni OrioliJul 22, 2026
  4. 0/2 mv: report missing destination leading directoryLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  5. 1/2 mv: name both source and destination when rename failsLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  6. Junio C HamanoJul 23, 2026
  7. 2/2 mv: check for missing destination directory before renamingLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  8. Junio C HamanoJul 23, 2026
  9. Junio C HamanoJul 23, 2026
  10. Lucas Zamboni OrioliJul 23, 2026
  11. Junio C HamanoJul 23, 2026
  12. Junio C HamanoJul 23, 2026
  13. Junio C HamanoJul 26, 2026
  14. Lucas Zamboni OrioliJul 26, 2026
  15. 0/2 mv: report missing destination leading directoryLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  16. 1/2 mv: name both source and destination when rename failsLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  17. 2/2 mv: check for missing destination directory before renamingLucas Zamboni Orioli via GitGitGadget, Jul 23, 2026
  18. Pablo SabaterJul 26, 2026
  19. 0/2 mv: report missing destination leading directoryLucas Zamboni Orioli via GitGitGadget, Jul 26, 2026
  20. 1/2 mv: name both source and destination when rename failsLucas Zamboni Orioli via GitGitGadget, Jul 26, 2026
  21. 2/2 mv: reject a destination whose leading path is missing or a symlinkLucas Zamboni Orioli via GitGitGadget, Jul 26, 2026
  22. Junio C HamanoJul 27, 2026
  23. Lucas Zamboni OrioliJul 30, 2026
  24. Junio C HamanoJul 26, 2026
  25. 0/2 mv: report missing destination leading directoryLucas Zamboni Orioli via GitGitGadget, Jul 30, 2026
  26. 1/2 mv: name both source and destination when rename failsLucas Zamboni Orioli via GitGitGadget, Jul 30, 2026
  27. 2/2 mv: reject a destination whose leading path is missing or a symlinkLucas Zamboni Orioli via GitGitGadget, Jul 30, 2026
  28. Junio C HamanoJul 30, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.