Having done this before, I'll offer two solutions. Note that #1 is typically the better long term solution, but it has more pre-work to implement.
Solution #1: One repo instead of two
There are many different ways to implement this, but they all converge down to having only a single repository to maintain, instead of two with completely different histories. Some people use a private submodule to contain the secrets, or different branches that only exist in the private repo that they keep rebasing, or environmental variables, or my personal preference which is untracked (using .gitignore
'd) config files that contain the secrets with example templates so each developer can populate their own configs. See questions like this one for more details.
Solution #2: Automate creating repo 2 from repo 1
The idea here is to write a script (typically using git filter-repo) which makes all the changes you need to your repo, and is repeatable. Once you've perfected the script, you run it the first time and all of the commit IDs will change, but as long as you don't change the script and don't rewrite the source repo, all subsequent passes will recreate the same commit hashes1 and simply add more commits from your source repo starting from the same previous HEAD commit ID. This enables you to merge in new changes cleanly across repos without conflicts.
Note both of these solutions have some downsides:
With #1 you'll need to also rewrite your private repo, and reorganize the structure a bit to get your secrets working.
With #2 you'll likely have to rewrite your public repo again one final time while you perfect your script. This may not be a problem if it doesn't have many contributors yet.
1git-filter-repo
will only recreate the same commit hashes in subsequent passes if nothing about the commits needs to change. This is normally the case since author and committer dates from existing commits are preserved by git-filter-repo
. If your script does something outside of git-filter-repo
or uses an option that will change a committer date to "now", consider hard-coding it to a specific date so the hash IDs are predictable and constant.