Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

- **Volume Mounting**: Supports symbolic links or file copy modes
- **Configuration Inheritance**: Child worktrees automatically inherit parent settings
- **Safe Cleanup**: Modified files are preserved during unsync
- **Safe Cleanup**: Modified or unrelated copied contents are preserved during unsync
- **AI Agent Optimized**: Create worktree + configure environment with a single command

## 📦 Installation
Expand Down Expand Up @@ -62,7 +62,7 @@ git volume status
| -------------------------- | -------------------------------------------------------- |
| `git volume init` | Create global directory and sample configuration file |
| `git volume sync` | Mount volumes to current worktree based on configuration |
| `git volume unsync` | Remove mounted volumes (modified files are preserved) |
| `git volume unsync` | Remove mounted volumes (modified or unrelated contents are preserved) |
| `git volume status` | Display current volume status |
| `git volume global add` | Copy files to global storage (`~/.git-volume`) |
| `git volume global list` | List files in global storage (tree view) |
Expand All @@ -84,7 +84,7 @@ volumes:
# Mount from global storage (~/.git-volume)
- "@global/secrets/prod.key:config/key"

# Directory mount (copies entire directory)
# Directory mount (overlay-copies source entries into target directory)
- mount: "configs:app/configs"
mode: "copy"
```
Expand All @@ -94,7 +94,11 @@ volumes:
| Mode | Description | Use Case |
| ------ | -------------------- | ---------------------------------------------------- |
| `link` | Create symbolic link | Local development (changes reflect immediately) |
| `copy` | Copy file | Docker builds (environments without symlink support) |
| `copy` | Copy file or overlay-copy directory | Docker builds (environments without symlink support) |

### Copy-mode directory behavior

When `mode: "copy"` uses a directory source, `sync` overlays the source entries into the target directory instead of deleting the target root directory. Existing unrelated files are preserved, file/symlink conflicts are replaced, and file-vs-directory conflicts fail safely. `status` and `unsync` operate on the copied source subset rather than requiring the whole target directory to match exactly.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This paragraph contains a lot of important information about the new overlay behavior. To improve readability, consider breaking it down into a bulleted list. This will make it easier for users to quickly understand the different aspects of the copy mode for directories.

For example:

When `mode: "copy"` is used with a directory source, the behavior is as follows:
*   **`sync`**: Overlays source entries into the target directory.
    *   The target root directory is not deleted.
    *   Existing unrelated files are preserved.
    *   File/symlink conflicts are replaced by the source entry.
    *   File-vs-directory conflicts cause the operation to fail safely.
*   **`status` & `unsync`**: Operate only on the set of files copied from the source, ignoring other files in the target directory.

This suggestion should also be applied to the translated README.md files in docs/translations/.


## 🔄 Worktree Inheritance

Expand Down Expand Up @@ -151,8 +155,9 @@ volumes:

- **Symlink Source Rejection**: `sync` and `global add` reject symlink sources for security
- **Path Traversal Prevention**: All paths are validated to prevent directory escape attacks
- **Change Detection on Unsync**: Copied files and directories are preserved if modified
- **Change Detection on Status**: `status` reports `MODIFIED` when copied targets differ from source
- **Overlay Copy Safety**: Directory copy mode preserves unrelated target files, replaces file/symlink conflicts, and fails on file-vs-directory conflicts
- **Change Detection on Unsync**: `unsync` removes only the copied source subset and preserves modified or unrelated contents
- **Change Detection on Status**: `status` reports `MODIFIED` when copied source entries differ from target
- **Idempotent Sync**: Running `sync` multiple times always produces the same result

## 📄 License
Expand Down
3 changes: 3 additions & 0 deletions docs/specs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ git volume init --verbose 0
Mounts volumes to the current Worktree according to the `git-volume.yaml` configuration.
- Searches for settings in the current directory; if not found, traverses parent directories (towards the Git Common Dir) to inherit settings.
- Mounts files/directories according to the configured mode (`link` or `copy`).
- In `copy` mode with a directory source, overlays the source entries into the target directory instead of deleting the target root directory. Unrelated target files are preserved, file/symlink conflicts are replaced, and file-vs-directory conflicts fail safely.
- Rejects symlink sources for security.

### Usage
Expand Down Expand Up @@ -64,6 +65,7 @@ git volume sync --dry-run
### Purpose
Removes symbolic links or copied files created by the `sync` command.
- **Safety Mechanism**: If a file mounted in `copy` mode has been modified, deletion is skipped to prevent data loss.
- For directory sources in `copy` mode, removes only the copied source subset. Unrelated files already present in the target directory are preserved.

### Usage
```bash
Expand Down Expand Up @@ -91,6 +93,7 @@ git volume unsync --dry-run
Displays a list of the status of currently configured volumes.
- Shows Source, Target, Mode (Link/Copy), and Status.
- Common status values include `OK (Linked)`, `OK (Copied)`, `MODIFIED`, `NOT MOUNTED`, and `MISSING (Source)`.
- For directory sources in `copy` mode, `OK (Copied)` means every copied source entry matches in the target directory; extra unrelated target files do not affect status.

### Usage
```bash
Expand Down
17 changes: 11 additions & 6 deletions docs/translations/README_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

- **Volume-Mounting**: Unterstützung für symbolische Links oder Dateikopien
- **Konfigurationsvererbung**: Kind-Worktrees erben automatisch die Eltern-Konfiguration
- **Sichere Bereinigung**: Vom Benutzer geänderte Dateien werden nicht gelöscht
- **Sichere Bereinigung**: Vom Benutzer geänderte oder nicht zugehörige Inhalte werden bei `unsync` nicht gelöscht
- **KI-Agenten-optimiert**: Worktree erstellen + Umgebung konfigurieren mit einem einzigen Befehl

## 📦 Installation
Expand Down Expand Up @@ -62,7 +62,7 @@ git volume status
| -------------------------- | ------------------------------------------------------------------- |
| `git volume init` | Globales Verzeichnis und Beispielkonfiguration erstellen |
| `git volume sync` | Volumes basierend auf Konfiguration im aktuellen Worktree einbinden |
| `git volume unsync` | Eingebundene Volumes entfernen (geänderte Dateien bleiben erhalten) |
| `git volume unsync` | Eingebundene Volumes entfernen (geänderte oder nicht zugehörige Inhalte bleiben erhalten) |
| `git volume status` | Aktuellen Volume-Status anzeigen |
| `git volume global add` | Dateien in den globalen Speicher kopieren (`~/.git-volume`) |
| `git volume global list` | Dateien im globalen Speicher auflisten (Baumansicht) |
Expand All @@ -84,7 +84,7 @@ volumes:
# Aus globalem Speicher einbinden (~/.git-volume)
- "@global/secrets/prod.key:config/key"

# Verzeichnis-Mounting (kopiert gesamtes Verzeichnis)
# Verzeichnis-Mounting (kopiert nur die Source-Einträge als Overlay in das Zielverzeichnis)
- mount: "configs:app/configs"
mode: "copy"
```
Expand All @@ -94,7 +94,11 @@ volumes:
| Modus | Beschreibung | Anwendungsfall |
| ------ | --------------------------- | ----------------------------------------------- |
| `link` | Symbolischen Link erstellen | Lokale Entwicklung (Änderungen sofort wirksam) |
| `copy` | Datei kopieren | Docker-Builds (Umgebungen ohne Symlink-Support) |
| `copy` | Datei kopieren / Verzeichnis als Overlay kopieren | Docker-Builds (Umgebungen ohne Symlink-Support) |

### Verzeichnisverhalten im Copy-Modus

Wenn `mode: "copy"` ein Verzeichnis als Source verwendet, legt `sync` die Source-Einträge als Overlay in das Zielverzeichnis, ohne das Zielwurzelverzeichnis zu löschen. Nicht zugehörige vorhandene Dateien bleiben erhalten, Datei-/Symlink-Konflikte werden ersetzt und Datei-gegen-Verzeichnis-Konflikte schlagen sicher fehl. `status` und `unsync` arbeiten ebenfalls auf dem kopierten Source-Subset, statt eine exakte Übereinstimmung des gesamten Zielverzeichnisses zu verlangen.

## 🔄 Worktree-Vererbung

Expand Down Expand Up @@ -151,8 +155,9 @@ volumes:

- **Ablehnung symbolischer Quellen**: `sync` und `global add` lehnen Quellen ab, die symbolische Links sind
- **Pfad-Traversal-Schutz**: Alle Pfade werden validiert, um Verzeichnis-Escape-Angriffe zu verhindern
- **Änderungserkennung bei Unsync**: Kopierte Dateien und Verzeichnisse werden beibehalten, wenn sie geändert wurden
- **Änderungserkennung bei Status**: Kopierte Dateien, die vom Original abweichen, werden als `MODIFIED` angezeigt
- **Overlay-Copy-Sicherheit**: Der Verzeichnis-Copy-Modus behält nicht zugehörige Zieldateien bei, ersetzt nur Datei-/Symlink-Konflikte und scheitert bei Datei-gegen-Verzeichnis-Konflikten
- **Änderungserkennung bei Unsync**: `unsync` entfernt nur das kopierte Source-Subset und behält geänderte oder nicht zugehörige Inhalte bei
- **Änderungserkennung bei Status**: `status` zeigt `MODIFIED`, wenn kopierte Source-Einträge vom Ziel abweichen
- **Idempotentes Sync**: Mehrfaches Ausführen von `sync` erzeugt immer das gleiche Ergebnis

## 📄 Lizenz
Expand Down
17 changes: 11 additions & 6 deletions docs/translations/README_es.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

- **Montaje de volúmenes**: Soporte para enlaces simbólicos o copia de archivos
- **Herencia de configuración**: Los árboles de trabajo hijos heredan automáticamente la configuración del padre
- **Limpieza segura**: Los archivos modificados por el usuario no se eliminan
- **Limpieza segura**: El contenido modificado por el usuario o no relacionado no se elimina durante `unsync`
- **Optimizado para agentes IA**: Crear árbol de trabajo + configurar entorno con un solo comando

## 📦 Instalación
Expand Down Expand Up @@ -62,7 +62,7 @@ git volume status
| -------------------------- | --------------------------------------------------------------- |
| `git volume init` | Crear directorio global y archivo de configuración ejemplo |
| `git volume sync` | Montar volúmenes en el árbol de trabajo actual |
| `git volume unsync` | Eliminar volúmenes montados (se preservan archivos modificados) |
| `git volume unsync` | Eliminar volúmenes montados (se preserva el contenido modificado o no relacionado) |
| `git volume status` | Mostrar el estado actual de los volúmenes |
| `git volume global add` | Copiar archivos al almacenamiento global (`~/.git-volume`) |
| `git volume global list` | Listar archivos en el almacenamiento global (vista árbol) |
Expand All @@ -84,7 +84,7 @@ volumes:
# Montar desde almacenamiento global (~/.git-volume)
- "@global/secrets/prod.key:config/key"

# Montaje de directorios (copia el directorio completo)
# Montaje de directorios (copia en overlay solo las entradas del source al directorio target)
- mount: "configs:app/configs"
mode: "copy"
```
Expand All @@ -94,7 +94,11 @@ volumes:
| Modo | Descripción | Caso de uso |
| ------ | ---------------------- | ------------------------------------------------------------------- |
| `link` | Crear enlace simbólico | Desarrollo local (los cambios se reflejan al instante) |
| `copy` | Copiar archivo | Compilaciones Docker (entornos sin soporte para enlaces simbólicos) |
| `copy` | Copiar archivo / copiar directorio en overlay | Compilaciones Docker (entornos sin soporte para enlaces simbólicos) |

### Comportamiento de directorios en modo copy

Cuando `mode: "copy"` usa un directorio como source, `sync` superpone las entradas del source en el directorio target sin borrar el directorio raíz target. Los archivos existentes no relacionados se preservan, los conflictos con archivo/enlace simbólico se reemplazan y los conflictos archivo-vs-directorio fallan de forma segura. `status` y `unsync` también operan sobre el subconjunto copiado del source, no sobre una coincidencia exacta de todo el directorio.

## 🔄 Herencia de árboles de trabajo

Expand Down Expand Up @@ -151,8 +155,9 @@ volumes:

- **Rechazo de fuentes simbólicas**: `sync` y `global add` rechazan fuentes que son enlaces simbólicos por seguridad
- **Prevención de recorrido de rutas**: Todas las rutas se validan para prevenir ataques de escape de directorio
- **Detección de cambios en Unsync**: Los archivos y directorios copiados se preservan si fueron modificados
- **Detección de cambios en Status**: Los archivos copiados que difieren del origen se muestran como `MODIFIED`
- **Seguridad de copia overlay**: El modo copy de directorios preserva archivos target no relacionados, reemplaza solo conflictos de archivo/enlace simbólico y falla en conflictos archivo-vs-directorio
- **Detección de cambios en Unsync**: `unsync` elimina solo el subconjunto copiado del source y preserva el contenido modificado o no relacionado
- **Detección de cambios en Status**: `status` muestra `MODIFIED` cuando las entradas copiadas del source difieren del target
- **Sync idempotente**: Ejecutar `sync` múltiples veces siempre produce el mismo resultado

## 📄 Licencia
Expand Down
17 changes: 11 additions & 6 deletions docs/translations/README_fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

- **Montage de volumes** : Support des liens symboliques ou de la copie de fichiers
- **Héritage de configuration** : Les arbres de travail enfants héritent automatiquement de la configuration parent
- **Nettoyage sécurisé** : Les fichiers modifiés par l'utilisateur ne sont pas supprimés
- **Nettoyage sécurisé** : Le contenu modifié par l'utilisateur ou non lié n'est pas supprimé pendant `unsync`
- **Optimisé pour les agents IA** : Créer un arbre de travail + configurer l'environnement en une seule commande

## 📦 Installation
Expand Down Expand Up @@ -62,7 +62,7 @@ git volume status
| -------------------------- | ------------------------------------------------------------------- |
| `git volume init` | Créer le répertoire global et le fichier de configuration exemple |
| `git volume sync` | Monter les volumes dans l'arbre de travail actuel |
| `git volume unsync` | Supprimer les volumes montés (les fichiers modifiés sont préservés) |
| `git volume unsync` | Supprimer les volumes montés (le contenu modifié ou non lié est préservé) |
| `git volume status` | Afficher le statut actuel des volumes |
| `git volume global add` | Copier des fichiers dans le stockage global (`~/.git-volume`) |
| `git volume global list` | Lister les fichiers du stockage global (vue arborescente) |
Expand All @@ -84,7 +84,7 @@ volumes:
# Monter depuis le stockage global (~/.git-volume)
- "@global/secrets/prod.key:config/key"

# Montage de répertoires (copie le répertoire entier)
# Montage de répertoires (copie en overlay uniquement les entrées source dans le répertoire cible)
- mount: "configs:app/configs"
mode: "copy"
```
Expand All @@ -94,7 +94,11 @@ volumes:
| Mode | Description | Cas d'utilisation |
| ------ | ------------------------ | ------------------------------------------------------- |
| `link` | Créer un lien symbolique | Développement local (les modifications sont immédiates) |
| `copy` | Copier le fichier | Builds Docker (environnements sans support symlink) |
| `copy` | Copier le fichier / copier un répertoire en overlay | Builds Docker (environnements sans support symlink) |

### Comportement des répertoires en mode copy

Quand `mode: "copy"` utilise un répertoire source, `sync` superpose les entrées source dans le répertoire cible sans supprimer le répertoire racine cible. Les fichiers existants non liés sont préservés, les conflits fichier/lien symbolique sont remplacés, et les conflits fichier-vs-répertoire échouent de manière sûre. `status` et `unsync` fonctionnent aussi sur le sous-ensemble copié depuis la source au lieu d'exiger que tout le répertoire cible corresponde exactement.

## 🔄 Héritage des arbres de travail

Expand Down Expand Up @@ -151,8 +155,9 @@ volumes:

- **Rejet des sources symboliques** : `sync` et `global add` rejettent les sources qui sont des liens symboliques pour la sécurité
- **Prévention de traversée de chemin** : Tous les chemins sont validés pour prévenir les attaques d'échappement de répertoire
- **Détection de modifications à l'Unsync** : Les fichiers et répertoires copiés sont préservés s'ils ont été modifiés
- **Détection de modifications au Status** : Les fichiers copiés différant de l'original sont affichés comme `MODIFIED`
- **Sécurité de la copie overlay** : Le mode copy des répertoires préserve les fichiers cible non liés, remplace seulement les conflits fichier/lien symbolique et échoue sur les conflits fichier-vs-répertoire
- **Détection de modifications à l'Unsync** : `unsync` supprime uniquement le sous-ensemble copié depuis la source et préserve le contenu modifié ou non lié
- **Détection de modifications au Status** : `status` affiche `MODIFIED` quand les entrées copiées depuis la source diffèrent de la cible
- **Sync idempotent** : Exécuter `sync` plusieurs fois produit toujours le même résultat

## 📄 Licence
Expand Down
Loading
Loading