Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ugultopu/120e87adbecfbb25084a348e70aa6cef to your computer and use it in GitHub Desktop.
Save ugultopu/120e87adbecfbb25084a348e70aa6cef to your computer and use it in GitHub Desktop.
git filter-repo --email-callback ' return b"new_email_address" if email == b"old_email_address" else email '

Documentation

If git-filter-repo is not installed, you have to install it. git-filter-repo is a program:

  1. Developed by Elijah Newren, who is a veteran contributor to Git.
  2. Endorsed by Git as the replacement for the git-filter-branch program, which had numerous issues.

For reasons that I don't know, it has to be installed separately, instead of being included in a Git distribution. At least this is the case in the version of Git that I'm using.

Installation

Installing git-filter-repo is very easy, since it is a single-file, self-contained Python script. That is, all you need to do is to copy this Python file to somewhere in your PATH, without needing to install any other things whatsoever.

If you are using a package manager, you can install it using your package manager, as described in the INSTALL document.

However, a downside of using a package manager is, as far as I can tell, most package managers specify dependencies as specific versions, instead of a range of versions. That is, for example if you use Homebrew, as of now, the git-filter-repo dependencies are specified as:

  • depends_on "git"
  • depends_on "python@3.9"

This means:

  • Version of Git that is currently available in Homebrew (which is supposed to be the latest version).
  • Version of Python 3.9 that is currently available in Homebrew (which is supposed to be the latest version).

This means even if you have, say:

  • Git 2.22 or higher from Xcode Command Line Tools.
  • Python 3.5 or higher, again, from Xcode Command Line Tools.

which satisfies the dependencies of git-filter-repo, installing git-filter-repo using Homebrew will, as of now, install:

  • Git 2.30.1
  • Python 3.9.1

even though the versions of Git and Python you currently have already satisfy the dependency requirements.

Hence, if you know that you satisfy the dependencies for it and don't want to install extraneous software, you can manually put the git-filter-repo script to somewhere in your PATH. You can also use the following script to do it for you:

#!/usr/bin/env python3

"""
MIT License

Copyright (c) 2021 Utku Gultopu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

"""
Download the latest release version of the specified file from the
specified GitHub repository and install it to specified directory.
"""

from http.client import HTTPSConnection
from os import chmod, symlink

GITHUB_REPOSITORY = 'newren/git-filter-repo'
FILE_PATH = 'git-filter-repo'
FILE_NAME  = FILE_PATH.split('/')[-1]
INSTALLATION_DIRECTORY  = '/usr/local/bin'

# Get the latest tag
connection = HTTPSConnection('github.com')
connection.request('HEAD', f'/{GITHUB_REPOSITORY}/releases/latest')
tag = connection.getresponse().getheader('location').split('/')[-1]

# Set file names according to latest tag
tagged_file_name = f'{FILE_NAME}-{tag}'
file_path = f'{INSTALLATION_DIRECTORY}/{tagged_file_name}'

# Get the file and install it to specified path, appending the tag to
# the name
with open(file_path, 'wb') as file:
    connection = HTTPSConnection('raw.githubusercontent.com')
    connection.request('GET', f'/{GITHUB_REPOSITORY}/{tag}/{FILE_PATH}')
    file.write(connection.getresponse().read())
    chmod(file_path, 0o755)

# Create a symlink pointing to the installed version
symlink(f'{tagged_file_name}', f'{INSTALLATION_DIRECTORY}/{FILE_NAME}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment