From: Michael Montalbo Date: Sun, 23 Aug 2026 17:18:45 GMT Subject: [RFC PATCH 01/14] organize: add the git organize builtin Message-ID: <20260823171915.2662373-2-mmontalbo@gmail.com> In-Reply-To: <20260823171915.2662373-1-mmontalbo@gmail.com> Add "git organize", a builtin that reconciles a source tree against a layout the project declares. A project records where each file belongs, and git organize reports the files that sit elsewhere and, on request, moves them into place. As .gitignore declares what stays untracked and .mailmap declares canonical author names, git organize adds .gitorganize, which declares the directory a file belongs in. .gitorganize has three sections. [scope] lists the pathspecs of the files in scope, one per line; with no [scope] section nothing is in scope. [layout] is the project's placement map, hand-authored: ordered "label:value = directory" rules, and a file takes the directory of the first rule its labels satisfy, so rule order matters. Git lists role:public = . and role:program = . ahead of the component rules, so an interface header or a program that also matches a component stays at root. [labels] records each file's labels, one line per source in scope with its key=value labels. "git organize status" reads [labels] and reports the files that sit outside their directory, the backlog, and a recorded path that no longer exists. It runs nothing and changes nothing. "git organize apply" moves each out-of-place file into its directory as one git apply --index transaction; a content-identical rename lets git log --follow and git blame track the file. It stages the result and repoints each moved file's [labels] line to its new path. The .gitorganize reader and writer live in organize/gitorganize-format.c; the engine that plans and applies the moves lives in organize/organize.c. Signed-off-by: Michael Montalbo --- .gitignore | 1 + Documentation/git-organize.adoc | 82 ++++++++ Documentation/meson.build | 1 + Makefile | 3 + builtin.h | 1 + builtin/organize.c | 110 +++++++++++ command-list.txt | 1 + git.c | 1 + meson.build | 3 + organize/gitorganize-format.c | 261 ++++++++++++++++++++++++++ organize/gitorganize-format.h | 38 ++++ organize/organize.c | 320 ++++++++++++++++++++++++++++++++ organize/organize.h | 77 ++++++++ t/meson.build | 1 + t/t0096-organize.sh | 185 ++++++++++++++++++ 15 files changed, 1085 insertions(+) create mode 100644 Documentation/git-organize.adoc create mode 100644 builtin/organize.c create mode 100644 organize/gitorganize-format.c create mode 100644 organize/gitorganize-format.h create mode 100644 organize/organize.c create mode 100644 organize/organize.h create mode 100755 t/t0096-organize.sh diff --git a/.gitignore b/.gitignore index 4da58c6754..b85ce2b13a 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,7 @@ /git-mv /git-name-rev /git-notes +/git-organize /git-p4 /git-pack-redundant /git-pack-objects diff --git a/Documentation/git-organize.adoc b/Documentation/git-organize.adoc new file mode 100644 index 0000000000..4ff76f5c13 --- /dev/null +++ b/Documentation/git-organize.adoc @@ -0,0 +1,82 @@ +git-organize(1) +=============== + +NAME +---- +git-organize - Reconcile a source tree against a declared layout + + +SYNOPSIS +-------- +[verse] +'git organize status' +'git organize apply' + + +DESCRIPTION +----------- +A project declares where each of its files belongs, and git organize +reports the files that sit elsewhere and, on request, moves them into +place. As `.gitignore` declares what stays untracked and `.mailmap` +declares canonical author names, `.gitorganize` declares the directory a +file belongs in. + +`.gitorganize` at the repository root has three sections. `[scope]` names +the files in scope, one pathspec per line; with no `[scope]` section +nothing is in scope. `[layout]` is the project's placement map, authored by +hand: ordered `