Open-sourcing the wallet tracker this week took longer than expected, and the delay was the useful part.
The plan was simple: strip my own wallet addresses out of the config, write a README, flip the repo to public. The first step is where it went sideways.
Deleting a file does not delete it
The repository had a tracked .env file. Not .env.example, an actual .env, committed on purpose with a comment saying "public, non-secret config." It held every wallet address I track, plus the mining payout address.
Removing it from the current files takes one command. But git keeps every version of every file ever committed. The addresses were in that file across five commits, and in .env.example across two more. Anyone who cloned the public repo could run git log -p and read all of them, no matter what the latest commit looked like.
There were no secrets. No passwords, no API keys, no connection strings. The one credential-shaped value in the whole history was a placeholder reading change-me. That part had been done right from the start.
But wallet addresses are a specific kind of public. Anyone with one can watch that balance and every transaction, forever, and a repository under my name ties them to me permanently. That is a different thing from an address on a contact page offered for payments. It is a map of what I hold.
The two options
You can rewrite history. Tools exist to scrub a file from every commit and force-push the result. It works, and it is fiddly, and every clone anyone already has still contains the old history.
Or you can start over. Copy the current files into a fresh directory, initialize a new repository, one commit, nothing before it. The private repo keeps its full history for me. The public one has none of it.
For a personal project with a few dozen commits, starting over is the obvious call. The history had no value to anyone else, and a clean single commit has no surprises in it.
What I actually did
Before the copy, a search of every file for anything that looked like an address: 0x followed by forty hex characters, bc1 followed by a run of characters, the shape of a Solana or TRON address. Then the same search across the entire history of the original, not just the working tree:
git log -p --all | grep -E '0x[a-fA-F0-9]{40}'
Then a search for my own name, the company name, internal hostnames, anything that pointed back at infrastructure the public did not need to know about. The app's name in a cookie, a hash salt, and a default database name all said "tofte." None of that was sensitive. All of it got genericized anyway, because a stranger running the tool should not find someone else's company name in their browser cookies.
Then the .gitignore got stricter than it was: every .env file ignored except the example. That does not stop a deliberate git add -f, but it stops the accident that caused this in the first place.
Then the copy, the new repo, one commit, push.
The check worth running on the pushed result
After pushing, I fetched the remote back and searched the tree that actually landed on GitHub, not the local copy. The two should be identical. Confirming it took ten seconds and removed the last "should be."
That habit, verifying the thing that shipped rather than the thing you meant to ship, is most of what separates a clean open-source release from an apology post.
The short version
If you are about to make a repository public:
- Search the working tree for addresses, keys, hostnames, and your own name.
- Search the history for the same things.
git log -p --allis your friend. - If anything turns up in history, start a fresh repository rather than trying to scrub the old one.
- After pushing, search what is on the remote.
The repo is at github.com/Gpatrickj7/tofte-wallet-tracker-. The addresses are not.