I have a project where I'd started working on my old laptop and then continued on my new one. On my old laptop I had properly configured Git with user.name and user.email, but when I switched to my new one I just cloned the repo and continued working without configuring user.name and user.email. As a result, the commits I made from my new laptop were attributed to my local machine's user for user.name and [computer_name]@local for user.email. I wanted to amend all the commits made from my new laptop and found the way to do it here.
git rebase -r <last commit from my old laptop> \
--exec 'git commit --amend --no-edit --reset-author'
Note, I'm the only one working on this repo, so rewriting history was not a big problem. However, one thing that did go wrong was that all the tags and releases I had created in my Git repo where left orphaned. GitHub shows me a message next to each tag that reads something like this:
~"this tag points to a commit outside any of the repository branches, or points to a different repo"~.
This is because amending the commit's author changes its identifying hash. So the tags point to the hashes of the old commits before the rebase command.
So, need to re-apply each tag to the new commit that corresponds to the old one it's pointing to.
How do I do that?
I managed to do this with a combination of
rev-list,awk,logandtag.Here's a breakdown of what it does:
git rev-list --all --tags: Lists all the commits that are reachable from any reference (branches, tags) in the repository.while read commit; do ... done: Reads each commit ID from the output ofgit rev-listand executes the following commands for each commit.new_commit=$(git log --format="%H" -n 1 $commit): Retrieves the new commit ID corresponding to the old commit ID by using the%Hformat option, which represents the full commit hash.git tag -f $(git tag --contains $commit) $new_commit: Reapplies the tags that contain the old commit ID ($commit) to the corresponding new commit ID ($new_commit) using thegit tagcommand with the-f(force) option. This overwrites any existing tags on the new commits with the same name.With this, each old tag will be repositioned to point to the corresponding new commit ID.
P.S.: Full disclosure, I used an AI assistant to figure this out.