A long time ago - and long before I joined the project - my project was migrated from clearcase to git. This migration led to the following file layout:
.
├── bar
│ ├── bar.c
│ └── bar.h
├── foo
│ ├── foo.c
│ └── foo.h
└── patches
├── bar
│ └── bar.c
└── foo
└── foo.h
On the day of the clearcase to git migration, patch and patched files were mostly copies with some -mostly- minor changes that were the reflect of clearcase differences.
The build system makes the patches hide the patched files. Patched files have been kept as a testimony of the patches that had been done in the ancient clearcase time. Patched files have (normally) experienced no changes since the migration.
Developers of the team have always feel really confused that when changing bar/bar.h
the implementation file that needs to be updated is patches/bar/bar.c
and not bar/bar.c
which is just a confusing testimony of the ancient times.
Now comes the time to apply these patches!
Now comes the time for bar/bar.c
to become the real source file again and for patches/bar/bar.c
to get back to the ancient times (Nonetheless bar/bar.c
shall reflect the git change history of patches/bar/bar.c
).
I see two options:
Option 1
Tricking the devs into believing there has never been a patch!
# This totally is a pseudo script. Sorry, friday night, not at work anymore!
pfile=patches/bar/bar.c
ofile=bar/bar.c
for commit in $(git log -- pfile)
git show commit:pfile > ofile
git commit -m"%B" --date %aN --author %cI
(This might be doable by some sort of rebase I haven't worked on today, feel free to improve)
Pros
git log -- bar/bar.c
really shows the history of the file with the application of the clearcase patch as one of the top commits.- If I want to run a filter to move
foo
andbar
to their own repo, the history will be preserved (and clean)
Cons
- This adds a lot of commit!
- Does not easily preserves commit coherency: if commit 01234567 modified both
bar/bar.h
andpatches/bar/bar.c
, this will now appear in two different commits
Option 2
The commit saving way. It can be found eg here:
git rm bar/bar.c
git commit -m 'Remove unpatched clearcase file'
git mv patches/bar/bar.c bar/bar.c
git commit -m 'Apply clearcase and git patches'
Pros
- Few commits added
- If I set
git config log.follow true
(thanks @VonC), my fellow devs will be tricked in looking at the history but the initial clearcase patch. This shall be enough.
Cons
- Unless I put a lot of effort this is not resilient to future (and foreseen) subdirectory filters.
- Initial clearcase patch hidden. To see the unpatched file history, I'll need some git trickery now that
--follow
is the default or setting an aliasget_clearcase_patch
that will compute the diff.
The question
Is there a third option I haven't seen (which preserves history, I thought of some which doesn't of course ^^)? Are there any pros and cons I haven't seen? Which is the best solution?