Skip to content

ENH: Ingest ITKMGHIO into Modules/IO#6137

Merged
hjmjohnson merged 89 commits intoInsightSoftwareConsortium:mainfrom
hjmjohnson:ingest-MGHIO
Apr 28, 2026
Merged

ENH: Ingest ITKMGHIO into Modules/IO#6137
hjmjohnson merged 89 commits intoInsightSoftwareConsortium:mainfrom
hjmjohnson:ingest-MGHIO

Conversation

@hjmjohnson
Copy link
Copy Markdown
Member

@hjmjohnson hjmjohnson commented Apr 25, 2026

Ingests ITKMGHIO (FreeSurfer .mgh/.mgz ImageIO) from the standalone remote module into Modules/IO/MGHIO/, freshly redone on top of upstream/main using the v3 ingestion tooling at Utilities/Maintenance/RemoteModuleIngest/. Includes the per-commit pre-commit replay step (now working — fixed in this PR) and removes the previous Modules/Remote/MGHIO.remote.cmake fetch declaration; opts the module into CI.

What this PR is
  • Branch was previously 86 commits ahead with the older (pre-v3-tooling) ingest. Completely redone on top of latest upstream/main using the current ingest-remote-module.sh driver and the published whitelist + scaffolding-deny passes.
  • Upstream: https://github.com/InsightSoftwareConsortium/itkMGHImageIO @ af74507c1ddc82722637c37d1f5d169e3000553a.
  • Compliance Level 2 (carried forward verbatim from the previous MODULE_COMPLIANCE_LEVEL 2 declaration).
  • Destination: Modules/IO/MGHIO/.
Ingest mode & metrics
Metric Value
Upstream commits (all refs) 113
Surviving after whitelist + scaffolding-deny 81
Files in whitelisted tree 15 (include/, src/, test/, wrapping/, CMakeLists.txt, itk-module.cmake)
Largest single blob introduced well under the 700 KiB threshold
Content-links: .md5 / .shaNNN / .cid 0 / 0 / 3 (already CID-normalized upstream)
verify-cid-access.sh Modules/IO/MGHIO ✅ all 3 resolve

After the per-commit replay (see next section) the linearized history retains 60 non-merge upstream commits with original author / author-date preserved, plus 4 follow-up commits in this PR.

Per-commit pre-commit replay (now working — bug fixed in this PR)

Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py previously crashed on the very first merge commit because it invoked git cherry-pick without -m N. This PR includes the fix as 1f70efe288:

  • git rev-list --no-merges filters merge commits out of the replay list. Merge commits typically carry no content of their own; the non-merge commits we keep collectively reproduce the final tree, and git blame after the merge boundary still walks back to original authors because authorship is preserved on every commit.
  • The dropped-merge count is reported on stderr so reviewers see what was elided.
  • Defense-in-depth: if a merge ever reaches the cherry-pick loop anyway (custom rev range, etc.), parent-count from %P is checked and -m 1 is passed automatically.

Replay result for this branch:

Skipping 21 merge commit(s); their content arrives via the 65 non-merge commits.
Replaying 65 commits onto upstream/main...
  REWRITE e7d661feed → BUG: FIX: ITK warnings of deprecated EXCLUDE_FROM_ALL.
  REWRITE a96deb673c → STYLE: Rename ITK_DISALLOW_COPY_AND_ASSIGN to ITK_DISALLOW_COPY_AND_MOVE Fi...
  DROP    c37212f4d4 STYLE: Update clang-format to match ITK 2025-11-10
Done. kept=62 subject-rewritten=2 dropped-empty=1

Two commits had subjects without an ITK prefix (BUG:/COMP:/DOC:/ENH:/PERF:/STYLE:) and were normalized; the original subject is preserved as Original subject: <text> in the body. One historical style-only commit became empty under today's hooks and was dropped (today's hooks would have prevented it from existing in the first place).

Already-ingested modules (AnisotropicDiffusionLBR, GenericLabelInterpolator) can now be re-normalized in a follow-up sweep using the same fixed tooling.

Commit chain on this branch
SHA Subject
1f70efe288 COMP: Fix normalize-ingest-commits.py merge-commit handling
0e87992cf7 ENH: Enable MGHIO in CI via configure-ci
86a1a89951 COMP: Remove MGHIO.remote.cmake; now in-tree
7be615e423 DOC: Add README.md pointing at archived upstream for MGHIO
(60 commits) Linearized upstream history; original author / author-date preserved
b1bd26497e ENH: Adding Remote Module for ITKv4 (oldest replayed upstream commit, 2013-05-16)

git blame on any line in Modules/IO/MGHIO/ walks back to the original upstream author.

Verification done locally
  • ingest-remote-module.sh MGHIO IO --dry-run --keep-tempdir — clean, whitelist-verification pass green.
  • ingest-remote-module.sh MGHIO IO — merge created, 4 follow-up commits added.
  • verify-cid-access.sh Modules/IO/MGHIO — all 3 CIDs resolved from cache + IPFS.
  • normalize-ingest-commits.py --base upstream/main — completed cleanly with the fix; kept=62, subject-rewritten=2, dropped-empty=1.
  • gh pr view reports 19 files changed (15 ingested + 1 README + MGHIO.remote.cmake deletion + pyproject.toml enable + normalize-ingest-commits.py fix).

hjmjohnson and others added 30 commits May 16, 2013 10:18
A copy of the Slicer itkMGHImageIO mechanism for ITK.

The intent of this repository is to extract the itkMGHImageIO from
it's embedded Slicer only implementation and make it accessible to
any ITK compliant program.

This will be accomplished using the ITKv4 'Remote Module' mechanism
as defined at:
http://www.itk.org/Wiki/ITK/Policy_and_Procedures_for_Adding_Remote_Modules
The ITK_EXPORT define was set to nothing and had no
known remaining purpose.  It was removed to make the
over all code easier to understand.  There was,
understandably, a bit of confusion about the
need for this being pervasive in the code.

It is currently backwards compatible to have
this in code, but at some future point it will
be removed.
Following the new naming rules for ITK remote modules,
the remote module name should not contain the "ITK" prefix.
Add "EXCLUDE_FROM_ALL" tag for this remote module.
The headers in the test dir can be found
without explicitly including the directory.
Clean up the module dependency.
MGHIO does not depend on ITKTransform.
Remove "ITK" from the module name.
EXCLUDE_FROM_ALL is replaced by EXCLUDE_FROM_DEFAULT
in ITK commit:0a98a978509a9536e07c22cde254559cc3c7d417.
FIX: ITK warnings of deprecated EXCLUDE_FROM_ALL.
BUG: missing steps converting origin back to freesurfer space
existing logic couldn't handle filenames with a dot
before the filename extension.
existing logic couldn't handle filenames with a dot
before the filename extension.
The dynamically allocated variable must be deleted in the destructor.
Remove usage of reserved "__" prefix.
BUG: Fix KWStyle error for header guarder
To be consistent with ITK, ITK_OVERRIDE and ITK_NULLPTR are
added.
ENH: Add ITK_OVERRIDE and ITK_NULLPTR designations
Remove usage of reserved "__" prefix. The test
header needed to have the __prefix removed.
BUG: Fix KWStyle error for header guarderd in test
Convert MGHIO to ITKIOMGH to conform to the ITK
naming conventions for IO modules.  This places
the MGH IO for images with other IO modules in
the cmake system, and automatically identifies it
as needing to be registered.
After discussion with ITK team, it was determined that
the convention was mis-interpreted in the previous
patch.  Internal and Remote IO modules have different
naming conventions.

Since MGHIO is still an external IO library, it should
not use the internal IO naming conventions.

This reverts commit 7616415.
Make the MGHIO module a shared library like the
other IO modules.

ctest -R MGH
 1/14 Test InsightSoftwareConsortium#810: ITKIOMGHInDoxygenGroup ...........   Passed    0.05 sec
 2/14 Test InsightSoftwareConsortium#811: MGHFactoryCreationTest ...........   Passed    0.09 sec
 3/14 Test InsightSoftwareConsortium#812: MGHReadImagesTest_mgz ............   Passed    4.23 sec
 4/14 Test InsightSoftwareConsortium#813: MGHReadImagesTest_mgh ............   Passed    0.68 sec
 5/14 Test InsightSoftwareConsortium#814: MGHReadImagesTest_mgh.gz .........   Passed    4.11 sec
 6/14 Test InsightSoftwareConsortium#815: itkITKIOMGHInternalTests .........   Passed    0.08 sec
 7/14 Test InsightSoftwareConsortium#816: itkITKIOMGHOriginTest ............   Passed    4.16 sec
 8/14 Test InsightSoftwareConsortium#2356: MGHIOInDoxygenGroup ..............   Passed    0.04 sec
 9/14 Test InsightSoftwareConsortium#2357: MGHFactoryCreationTest ...........   Passed    0.07 sec
10/14 Test InsightSoftwareConsortium#2358: MGHReadImagesTest_mgz ............   Passed    4.23 sec
11/14 Test InsightSoftwareConsortium#2359: MGHReadImagesTest_mgh ............   Passed    0.68 sec
12/14 Test InsightSoftwareConsortium#2360: MGHReadImagesTest_mgh.gz .........   Passed    4.13 sec
13/14 Test InsightSoftwareConsortium#2361: itkMGHIOInternalTests ............   Passed    0.07 sec
14/14 Test InsightSoftwareConsortium#2362: itkMGHIOOriginTest ...............   Passed    4.13 sec
100% tests passed, 0 tests failed out of 14
The test cases used determined that all pixel
values were the same, but did not check that
the image meta-data was preserved during
writing!

The tests have been improved to demonstrate that
a bug has existed in the MGHIO writer for a very
long time.  If the DirectionCosine = Transpose(DirectionCosine)
then there was not problem.

A future patch will address the bug.
Previously the replay used ``git rev-list base..HEAD`` (which includes
merge commits) and then invoked ``git cherry-pick`` without ``-m N``.
``cherry-pick`` rejects merge commits without an explicit ``-m``, so
the very first merge in the upstream history aborted the entire
replay. This blocked applying the v3 ingestion strategy's per-commit
pre-commit replay step to any module whose upstream has merges in
its surviving history (which is most of them).

Fix:

* ``git rev-list --no-merges`` now drops merge commits from the
  replay list. Merge commits typically carry no content of their own;
  the non-merge commits we keep collectively reproduce the final
  tree, and ``git blame`` after the merge boundary still walks back
  to original authors because authorship is preserved on the
  non-merge commits.

* The dropped-merge count is reported on stderr so reviewers see
  what was elided.

* Defense-in-depth: if a merge ever reaches the cherry-pick loop
  anyway (e.g. someone calls the script with a custom rev range),
  detect it via the parent count from ``%P`` and pass ``-m 1`` so
  cherry-pick succeeds rather than crashing the run.

Surfaced while ingesting ITKMGHIO; would similarly bite any module
whose surviving history contains a merge commit.
Drop the standalone-build conditional inherited from the remote-module
days; once in-tree, the only path that matters is itk_module_impl().
Also drop the redundant cmake_minimum_required (ITK's root sets it)
and the project() VERSION/LANGUAGES (the ITK module system supplies
both via DEPENDS).

Brings the file in line with siblings such as
Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt
(post-ingest) and the established core IO modules
(e.g. Modules/IO/HDF5/CMakeLists.txt).

Addresses @dzenanz review comment on PR InsightSoftwareConsortium#6137.
@hjmjohnson
Copy link
Copy Markdown
Member Author

@dzenanz Addressed in 674e55d: the ingest merge commit (ENH: Ingest ITKMGHIO into Modules/IO) is now preserved as the boundary, and git rebase --rebase-merges upstream/main keeps the upstream PR-merge structure intact across this rebase. git log --merges upstream/main..HEAD now shows 5 merge commits (1 ingest + 4 from upstream history), and git blame walks back to the original upstream authors. The CMakeLists.txt simplification you asked for is in a180130.

* end-of-file-fixer stripped a trailing blank line
* gersemi reformatted the file to match ITK's house CMake style
  (block-arg layout, lowercase CMake command names)

Both hooks fired on the inherited upstream test driver.
gersemi reformatted Modules/IO/MGHIO/itk-module.cmake and
Modules/IO/MGHIO/src/CMakeLists.txt to match ITK's house CMake
style; the prior pass at this had only covered the test/ tree.
@hjmjohnson hjmjohnson merged commit 2e61183 into InsightSoftwareConsortium:main Apr 28, 2026
14 of 16 checks passed
@hjmjohnson hjmjohnson deleted the ingest-MGHIO branch April 28, 2026 02:02
hjmjohnson added a commit to InsightSoftwareConsortium/ITKMGHImageIO that referenced this pull request Apr 28, 2026
The MGHIO module was ingested into the main ITK source tree on
2026-04-28 via InsightSoftwareConsortium/ITK#6137 (merge commit
2e61183c46). Per the ITK ingestion strategy
(Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md),
the one-definition rule requires that any file now living at
Modules/IO/MGHIO/ in ITK no longer live at this upstream repo's
tree tip.

This commit:

- Removes the whitelisted files that transferred during ingest:
  include/, src/, test/, wrapping/, CMakeLists.txt,
  itk-module.cmake, CTestConfig.cmake.
- Adds MIGRATION_README.md at the repo root pointing users at the
  authoritative in-tree ITK location and linking the ingest PR.
- Leaves the pre-ingest history intact so blame, paper material,
  and historical references remain reachable.

After this PR merges, this repository will be marked ARCHIVED via
GitHub's repository settings (Danger Zone -> Archive this
repository), making it read-only.

Cloning ITK main gets the authoritative MGHIO module under
Modules/IO/MGHIO/. Cloning this repo after archival gets only the
MIGRATION_README pointer plus everything that was deliberately not
migrated.
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The upstream remote module's top-level CMakeLists.txt carried a
dual-mode preamble that supports both standalone (find_package(ITK)
+ ITKModuleExternal) and in-tree (itk_module_impl) builds.

Once the module lives under Modules/Filtering/, only the in-tree
branch is reachable -- the standalone branch is dead code, the
cmake_minimum_required and project() lines duplicate what ITK's
root CMake already owns.  Collapse the file to a single
itk_module_impl() call, matching every other in-tree
Modules/<Group>/<Name>/ module.

Per the standalone-build cleanup convention documented in
Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md
under "Standalone-build boilerplate cleanup (modes A/B)" and
applied previously to GenericLabelInterpolator (PR InsightSoftwareConsortium#6135) and
MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The module now lives at Modules/Filtering/FastBilateral/.  The
configure-time fetch declaration in Modules/Remote/ would otherwise
clone the (soon-to-be-archived) upstream and double-define the
module.

Mirrors the in-tree transition completed for GenericLabelInterpolator
(PR InsightSoftwareConsortium#6135) and MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The upstream remote module's top-level CMakeLists.txt carried a
dual-mode preamble that supports both standalone (find_package(ITK)
+ ITKModuleExternal) and in-tree (itk_module_impl) builds.

Once the module lives under Modules/Filtering/, only the in-tree
branch is reachable -- the standalone branch is dead code, the
cmake_minimum_required and project() lines duplicate what ITK's
root CMake already owns.  Collapse the file to a single
itk_module_impl() call, matching every other in-tree
Modules/<Group>/<Name>/ module.

Per the standalone-build cleanup convention documented in
Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md
under "Standalone-build boilerplate cleanup (modes A/B)" and
applied previously to GenericLabelInterpolator (PR InsightSoftwareConsortium#6135) and
MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The module now lives at Modules/Filtering/FastBilateral/.  The
configure-time fetch declaration in Modules/Remote/ would otherwise
clone the (soon-to-be-archived) upstream and double-define the
module.

Mirrors the in-tree transition completed for GenericLabelInterpolator
(PR InsightSoftwareConsortium#6135) and MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The upstream remote module's top-level CMakeLists.txt carried a
dual-mode preamble that supports both standalone (find_package(ITK)
+ ITKModuleExternal) and in-tree (itk_module_impl) builds.

Once the module lives under Modules/Filtering/, only the in-tree
branch is reachable -- the standalone branch is dead code, the
cmake_minimum_required and project() lines duplicate what ITK's
root CMake already owns.  Collapse the file to a single
itk_module_impl() call, matching every other in-tree
Modules/<Group>/<Name>/ module.

Per the standalone-build cleanup convention documented in
Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md
under "Standalone-build boilerplate cleanup (modes A/B)" and
applied previously to GenericLabelInterpolator (PR InsightSoftwareConsortium#6135) and
MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The module now lives at Modules/Filtering/FastBilateral/.  The
configure-time fetch declaration in Modules/Remote/ would otherwise
clone the (soon-to-be-archived) upstream and double-define the
module.

Mirrors the in-tree transition completed for GenericLabelInterpolator
(PR InsightSoftwareConsortium#6135) and MGHIO (PR InsightSoftwareConsortium#6137).
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The normalize-ingest-commits.py script replays each non-merge upstream
commit via cherry-pick and skips merges entirely.  The result loses
the upstream merge topology, which the strategy doc has always
mandated as preserved.  Reviewers flagged this on PRs InsightSoftwareConsortium#6135, InsightSoftwareConsortium#6137,
InsightSoftwareConsortium#6159, and InsightSoftwareConsortium#6161 before it became a rule violation.

This commit:

1. Adds a hard refuse-to-run guard to normalize-ingest-commits.py
   (exit 3 with deprecation notice unless --i-understand-this-linearizes
   is passed).  The guard names the replacement and points at the
   strategy doc.

2. Adds rewrite-history-merge-preserving.py — a git-filter-repo
   driven rewriter that walks every commit (merges included) and
   applies uniform text-blob normalization (trailing-whitespace strip
   + EOF-newline fix).  Implements the user-mandated Phase 1
   reference / Phase 2 traversal / Phase 3 verification architecture.

3. Updates INGESTION_STRATEGY.md with the "Linearization is forbidden"
   subsection, an allowed-tool table for per-commit re-formatting,
   and the new operator check that the merge count satisfies
   1 + UPSTREAM_INTERNAL_MERGES.

Language-specific formatters (clang-format, gersemi) are intentionally
NOT applied per blob — they require the destination's current config,
and applying them retroactively across upstream history would produce
spurious diffs.  The recommended pattern is a single
"STYLE: Apply current formatters" commit at the rewritten tip after
Phase 2 succeeds.
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The normalize-ingest-commits.py script replays each non-merge upstream
commit via cherry-pick and skips merges entirely.  The result loses
the upstream merge topology, which the strategy doc has always
mandated as preserved.  Reviewers flagged this on PRs InsightSoftwareConsortium#6135, InsightSoftwareConsortium#6137,
InsightSoftwareConsortium#6159, and InsightSoftwareConsortium#6161 before it became a rule violation.

This commit:

1. Adds a hard refuse-to-run guard to normalize-ingest-commits.py
   (exit 3 with deprecation notice unless --i-understand-this-linearizes
   is passed).  The guard names the replacement and points at the
   strategy doc.

2. Adds rewrite-history-merge-preserving.py — a git-filter-repo
   driven rewriter that walks every commit (merges included) and
   applies uniform text-blob normalization (trailing-whitespace strip
   + EOF-newline fix).  Implements the user-mandated Phase 1
   reference / Phase 2 traversal / Phase 3 verification architecture.

3. Updates INGESTION_STRATEGY.md with the "Linearization is forbidden"
   subsection, an allowed-tool table for per-commit re-formatting,
   and the new operator check that the merge count satisfies
   1 + UPSTREAM_INTERNAL_MERGES.

Language-specific formatters (clang-format, gersemi) are intentionally
NOT applied per blob — they require the destination's current config,
and applying them retroactively across upstream history would produce
spurious diffs.  The recommended pattern is a single
"STYLE: Apply current formatters" commit at the rewritten tip after
Phase 2 succeeds.
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The normalize-ingest-commits.py script replays each non-merge upstream
commit via cherry-pick and skips merges entirely.  The result loses
the upstream merge topology, which the strategy doc has always
mandated as preserved.  Reviewers flagged this on PRs InsightSoftwareConsortium#6135, InsightSoftwareConsortium#6137,
InsightSoftwareConsortium#6159, and InsightSoftwareConsortium#6161 before it became a rule violation.

This commit:

1. Adds a hard refuse-to-run guard to normalize-ingest-commits.py
   (exit 3 with deprecation notice unless --i-understand-this-linearizes
   is passed).  The guard names the replacement and points at the
   strategy doc.

2. Adds rewrite-history-merge-preserving.py — a git-filter-repo
   driven rewriter that walks every commit (merges included) and
   applies uniform text-blob normalization (trailing-whitespace strip
   + EOF-newline fix).  Implements the user-mandated Phase 1
   reference / Phase 2 traversal / Phase 3 verification architecture.

3. Updates INGESTION_STRATEGY.md with the "Linearization is forbidden"
   subsection, an allowed-tool table for per-commit re-formatting,
   and the new operator check that the merge count satisfies
   1 + UPSTREAM_INTERNAL_MERGES.

Language-specific formatters (clang-format, gersemi) are intentionally
NOT applied per blob — they require the destination's current config,
and applying them retroactively across upstream history would produce
spurious diffs.  The recommended pattern is a single
"STYLE: Apply current formatters" commit at the rewritten tip after
Phase 2 succeeds.
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The normalize-ingest-commits.py script replays each non-merge upstream
commit via cherry-pick and skips merges entirely.  The result loses
the upstream merge topology, which the strategy doc has always
mandated as preserved.  Reviewers flagged this on PRs InsightSoftwareConsortium#6135, InsightSoftwareConsortium#6137,
InsightSoftwareConsortium#6159, and InsightSoftwareConsortium#6161 before it became a rule violation.

This commit:

1. Adds a hard refuse-to-run guard to normalize-ingest-commits.py
   (exit 3 with deprecation notice unless --i-understand-this-linearizes
   is passed).  The guard names the replacement and points at the
   strategy doc.

2. Adds rewrite-history-merge-preserving.py — a git-filter-repo
   driven rewriter that walks every commit (merges included) and
   applies uniform text-blob normalization (trailing-whitespace strip
   + EOF-newline fix).  Implements the user-mandated Phase 1
   reference / Phase 2 traversal / Phase 3 verification architecture.

3. Updates INGESTION_STRATEGY.md with the "Linearization is forbidden"
   subsection, an allowed-tool table for per-commit re-formatting,
   and the new operator check that the merge count satisfies
   1 + UPSTREAM_INTERNAL_MERGES.

Language-specific formatters (clang-format, gersemi) are intentionally
NOT applied per blob — they require the destination's current config,
and applying them retroactively across upstream history would produce
spurious diffs.  The recommended pattern is a single
"STYLE: Apply current formatters" commit at the rewritten tip after
Phase 2 succeeds.
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 28, 2026
The normalize-ingest-commits.py script replays each non-merge upstream
commit via cherry-pick and skips merges entirely.  The result loses
the upstream merge topology, which the strategy doc has always
mandated as preserved.  Reviewers flagged this on PRs InsightSoftwareConsortium#6135, InsightSoftwareConsortium#6137,
InsightSoftwareConsortium#6159, and InsightSoftwareConsortium#6161 before it became a rule violation.

This commit:

1. Adds a hard refuse-to-run guard to normalize-ingest-commits.py
   (exit 3 with deprecation notice unless --i-understand-this-linearizes
   is passed).  The guard names the replacement and points at the
   strategy doc.

2. Adds rewrite-history-merge-preserving.py — a git-filter-repo
   driven rewriter that walks every commit (merges included) and
   applies uniform text-blob normalization (trailing-whitespace strip
   + EOF-newline fix).  Implements the user-mandated Phase 1
   reference / Phase 2 traversal / Phase 3 verification architecture.

3. Updates INGESTION_STRATEGY.md with the "Linearization is forbidden"
   subsection, an allowed-tool table for per-commit re-formatting,
   and the new operator check that the merge count satisfies
   1 + UPSTREAM_INTERNAL_MERGES.

Language-specific formatters (clang-format, gersemi) are intentionally
NOT applied per blob — they require the destination's current config,
and applying them retroactively across upstream history would produce
spurious diffs.  The recommended pattern is a single
"STYLE: Apply current formatters" commit at the rewritten tip after
Phase 2 succeeds.
@hjmjohnson hjmjohnson added this to the ITK 6.0 Release Candidate 1 milestone May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:IO Issues affecting the IO module area:Python wrapping Python bindings for a class area:Remotes Issues affecting the Remote module type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants