3

I've committed a bunch of commits to many repositories on Gitlab over two years. However I realized I hadn't set up the proper email.

I used git filter-branch to filter the history and change the user Email.

$ git filter-branch --env-filter '
OLD_EMAIL="old@example.com"
NEW_NAME="New Example"
NEW_EMAIL="new@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
  export GIT_COMMITTER_NAME="$NEW_NAME"
  export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
  export GIT_AUTHOR_NAME="$NEW_NAME"
  export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

then I force pushed these changes with git push --force. It updates the contributor on master branch.

After git push --force --tags origin 'refs/heads/master' it changes the contributor on tags, too.

Problem:
It does not change the commits on Activity Page. Go to {Repository} > Project information > activity (shows updated contributor) but clicking on any commit number --> it loads an commit with not updated contributor.

Question:
How to rewrite the proper history including commits published in the activity log.

torek
  • 448,244
  • 59
  • 642
  • 775
David Strauch
  • 147
  • 2
  • 11
  • 1
    I think I had a similar problem a few years ago and just ended up deleting the gitlab project and repushing the repo to a new project... won't all the activties back but will clear unwanted info from old activities – Alex028502 Dec 09 '21 at 09:11

1 Answers1

2

Activity stream is immutable

Unfortunately, the activity feed comes directly from the database event records and is completely separated from git once records are created. As far as I know, it is not possible to remove the entries in the activity feed, unless you have database level access.

However, it is possible to remove those commits completely using git-filter-repo and running a repository cleanup so that they can't be viewed in GitLab. The links will still exist in the activity feed, but you'll get a 404 page when trying to view the re-written/removed commit SHA.

Another possible workaround would be to remove the activity feed entirely -- to do this, simply export your project, then import it. If you do that before pushing the git-filter-repo changes, then all the activity for all commits will show as the timestamp in which you push those changes:

activity after pushing filter repo

If you do it after, there will simply be no activity in the feed at all:

import fresh with no activity log

Deep-cleaning references from GitLab

Going beyond commits on branches, GitLab keeps (additional) internal references that are normally not present on your local git repo when you clone it. Including references in merge requests, pipelines, notes, and other places. Even if you update your refs/heads/* you may need to update additional refs on the remote in order to see the change take effect in different places.

This will break certain UI pages and potentially lead to data loss, but is the only way to get GitLab to completely remove old references aside from deleting and re-creating the project.

Before starting MAKE A BACKUP of your repo by exporting it.

To completely change things, you'll need to alter these references as well:

refs/merge-requests/* for merge requests.
refs/pipelines/* for pipelines.
refs/environments/* for environments.
refs/keep-around/* are created as hidden refs to prevent commits referenced in the database from being removed

Unfortunately, GitLab doesn't let you access some of these "hidden refs" directly. To completely remove these references, you have to export your project to a tarball and restore the local git repo from the tarball, then apply the filter again, and push to the remote.

Export your project, then in the tarball there is a project.bundle file.

git clone --bare --mirror ./project.bundle myrepo
cd myrepo

Then use git-filter-repo to completely change the email everywhere.

# replace with your actual filter-repo command needed
git filter-repo --name-callback '...' --email-callback '...' --commit-callback '...'

Then force push back all the refs, including hidden refs:

# reset the origin
git remote remove origin
git remote add origin https://gitlab.example.com/<namespace>/<project_name>.git

# push all refs
git push origin --force 'refs/heads/*'

# tags
git push origin --force 'refs/tags/*'

# prevent dead links to commits that no longer exist
git push origin --force 'refs/replace/*'

After this, you need to initialize a repository cleanup using the commit-map generated by git filter-repo. It's located in the repo at ./filter-repo/commit-map. It looks something like this:

$ cat filter-repo/commit-map
old                                      new
87c5016db64c6e8f4fc0feba4810b17c2c2222b5 2bb77407040e8a658eceacdf3034d24cedcc1ecd
cea6d9aa25e52dd755b694876a482a158debc60a 9a9b1d1a845d1096f4d3734191f883b52ffac6e9
5f1ac8c5fa47ac393d5e3f24b4b9812aaefbf5d7 b659497ed15ab0a3191dc5c6451c9440ca10d6e4

With the commit-map in hand, go to settings -> repository -> cleanup and upload the commit-map file. You'll see a message:

Repository cleanup has started. You will receive an email once the cleanup operation is complete.

After some time (depends on repo size), the old commits should be completely gone.

In the activity feed, as mentioned, the links to old commits will still be there:

activity feed

But if you click on the link, the commit itself now produces a 404 and can't be viewed in GitLab (gone forever!):

commit 404 link

sytech
  • 29,298
  • 3
  • 45
  • 86
  • 1
    I've exported, deleted, and imported my repositories. That solved it for me because the activities weren't important to me. Many Thanks. – David Strauch Dec 11 '21 at 15:57