Motivation

Altium has their Altium365 cloud service, which includes Git version control. I wanted to mirror my Altium project to GitHub to add to my portfolio, since my GitHub currently has a lot of programming but not so much embedded projects to show.

Adding a new remote is the most obvious solution.

1
2
git remote add gh https://github.com/OWNER/REPOSITORY.git    # gh remote is for github
git push gh master

There are several issues:

  1. Altium does not work with ssh connections, only HTTPS. This is not a problem if you use HTTPS on GitHub.
  2. I had issues with Altium recognizing the gh remote as the primary remote, instead of the Altium 365 remote. Obviously, Altium doesn’t seem designed to deal with multiple remotes.
  3. The largest issue is that Altium sets up the user.email with the format $NAME@$DOMAIN@$MACHINE_NAME. This email format is not accepted on GitHub, so the commits do not get attributed to your GitHub account, and they appear in a ‘raw’ form as:

    $EMAIL authored and $EMAIL comitted on $DATE.

So I bodged together a script to resolve these issues which is probably against all good Git practice, but whatever (I’m not planning to have users contribute to the GitHub side - it will only be a read-only remote).

1
2
3
4
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL=${GIT_AUTHOR_EMAIL%@*}
export GIT_COMMITTER_EMAIL=${GIT_COMMITTER_EMAIL%@*}
' --tag-name-filter cat -- --branches --tags

This command will re-write history to remove everything after the second @ symbol, including the machine name. As we are re-writing history, copy the repository to a new directory. Do not modify the original, since rewriting history is risky and Altium probably relies on the format including the machine name.

Anyway I ChatGPT’d the rest, but it

  1. Copy all directories in a csv ($directory_name,$remote_url) to a ZZZ_GITHUB directory. Projects which are already in the github directory are compared by revision, and if the github copy is out of date then it is copied over.
  2. Reset --hard, since the script will be run rarely and a project might be modified but not committed.
  3. Rewrite history, remove machine name from author and committer emails.
  4. Add new remote and push.

Here’s the script, enjoy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash

# Step 1: Create the "ZZZ_GITHUB" folder if it doesn't exist
mkdir -p ZZZ_GITHUB

# Step 2: Read the list of repository names from "repositories_list.txt" and copy only the listed repositories
while IFS=',' read -r directory remote_url || [ -n "$directory" ]; do
    echo "Processing repository: $directory"
    source_dir="$directory"
    target_dir="ZZZ_GITHUB/$directory"

    # Check if the source directory is a valid Git repository
    if [ -d "$source_dir/.git" ] && git -C "$source_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
        # Check if the target directory is not present or is out of date
        if [ ! -d "$target_dir" ] || ! git -C "$source_dir" diff-index --quiet HEAD -- "$source_dir"; then
            # Copy the repository to ZZZ_GITHUB
            echo "Copy: $directory . . ."
            rm -rf "$target_dir"
            cp -r "$source_dir" "$target_dir"
            echo "Repository copied: $directory"
            git -C "$target_dir" reset --hard HEAD
            git -C "$target_dir" filter-branch --env-filter '
            export GIT_AUTHOR_EMAIL=${GIT_AUTHOR_EMAIL%@*}
            export GIT_COMMITTER_EMAIL=${GIT_COMMITTER_EMAIL%@*}
            ' --tag-name-filter cat -- --branches --tags
            git -C "$target_dir" remote set-url origin "$remote_url"
            git -C "$target_dir" push --force origin HEAD
            echo "Copied repository pushed to the remote: $directory"
        else
            echo "Repository is up to date: $directory"
        fi
    else
        echo "Invalid Git repository or directory not found: $directory"
    fi
done < repositories_list.txt

You can see this script working for the STM32WLE5 development board.