Reputation: 185
I did a terrible mistake at a current project. When I created my java project, I used a wrong subpackage.
The best case scenario would enable me to rename the package at my first commit and transitive change all following commits to the correct package name.
The reason is that I reference the commits and packages in a scientific paper. Commiting the rename now would be very unfortune.
Is there a way to apply this change transitive, so I dont have to edit all commits by hand? All commits are already pushed to the remote.
I am the only author and have all administrive privileges. I want to preserve the commit history - meaning i do not want to squash all commits. Their identity can be changed if necessary.
EDIT:
I applied the required change with both approaches and want to summarize for future reference.
The rebasing approach via git rebase -i
is very tedious for many commits.
One has to apply the neccesary changes on all commits to all files and all directories.
Due to the number of commits in my case, I was not able to do it without any mistakes, resulting in a few squashed commits.
Without the capabilities of grep
, find
or my editor, I would not have succeeded.
The command git filter-branch
as suggested by the answer https://stackoverflow.com/a/66122950/6783797 did the job reliably.
The changes to apply were:
Renaming the directories:
JAVADIR="$PWD/path/to/parent/package"
if [ -d "$JAVADIR/wrong" ]; then
mv "$JAVADIR/wrong" "$JAVADIR/right"
fi
To find the appropriate files, i piped find
and sed -i 's/wrong/right/g'
from the accepted answer.
Assembling these together gave:
git filter-branch --tree-filter "sh /path/to/rename_script.sh; find . -type f \( -iname '*.java' -o -iname '*.xml' \) | xargs -r sed -i 's/wrong/right/g'"
What I ended up with was a diverged branch, which I wanted to use on my remote. A quick search offered me this answer: https://stackoverflow.com/a/40201484/6783797
Upvotes: 1
Views: 253
Reputation: 6036
As @WilliamPursell suggested, in your case filter-branch
is the most suitable command. It is a very performant and flexible tool provided by git, but pay attention because it is dangerous if used inappropriately.
First of all, filter-branch
rewrites the history, the whole history if needed, and accepts several options. In your case the --tree-filter
because you need to change the content of one or more file I guess. The old commits are not lost forever, but they are still reachable because the old HEAD
is still pointed by refs/original/refs/heads/your_branch
. You can see the old commits using git log --all
. Given that you are alone on that project is certainly an advantage, no one is going to complain that their history, or part of it has been rewritten.
Honestly, I do not know if the backup branch created after the filter-branch
command stays there forever or after sometime it is automatically gced. I am sure that you cannot do another filter-branch
before deleting that pointer, unless you force it -f
.
After all these warnings, you probably are going to run something similar to this:
git filter-branch --tree-filter "sed -i 's/import my.wrong.package/import my.right.package;/g' target_file"
Upvotes: 2