Scientific Computing

Git commit PGP signing

Git signed commits help verify the Git author’s identity using PGP. Optionally, a user or organization can set rules requiring Git PGP signed commits on Git hosting providers such as GitHub and GitLab

PGP public keys can help verify author identity of Git commits, social media, website, etc. Setup GPG on the laptop:

  • Linux: apt install gnupg
  • macOS: brew install gnupg
  • Windows: winget install --id=GnuPG.Gpg4win

Generate a GPG keypair if one doesn’t already exist for yourself.

Export the GPG public and private key and import into GPG:

If one has Keybase, first export Keybase.io PGP key to GPG. If one does NOT have Keybase, use gpg --full-generate-key to generate a GPG keypair.

Verify PGP key:

gpg --list-secret-keys --keyid-format LONG

The first lines will be like:

sec   rsa4096/<public_hex>

The hexadecimal part after the / is a public reference to the GPG keypair.


Add Git provider such as GitHub or GitLab verified email address to the PGP key. To make commits “Verified” with the Git provider, at least one of the Git provider verified email addresses must match:

git config --get user.email

Use the GPG public ID below:

gpg --edit-key <public_hex>

In the interactive GPG session that launches, type

adduid

and enter Name and the Email address–which must exactly match the GitHub verified email address. I also add the @users.noreply.github.com fake email that I always use to avoid spam. Do adduid twice–once for the real GitHub verified email address and again for the github_username@users.noreply.github.com fake email.

Add “trust” from the GPG> prompt:

trust

Since it’s you, perhaps a trust level of 5 is appropriate. type

save

to save changes, which may not show up until exiting and reentering the GPG> prompt.

Configure Git to use the GPG public hex ID like:

git config --global user.signingkey <public_hex>

git config --global commit.gpgsign true

On Windows, even though “gpg” works from Windows Terminal, it’s essential to tell Git the full path to GPG.exe, otherwise Git will fail to sign commits.

git config --global gpg.program "C:\Program Files\GnuPG\bin\gpg.ex"

Find the path with:

where.exe gpg

Add the GPG public key to the Git provider. Copy and paste the output from this command into GPG Key of GitHub or GitLab. This is done only once per human, not once per device.

gpg --armor --export <public_hex>

Usage

GPG can be used to sign Git commits and tags, and can also be disabled per commit.

Verify Git PGP commit sign

Make a git commit after the procedure above, and see the signature notes:

git log --show-signature

it will start with

gpg: Signature made

Temporary disable Git commit sign

If you temporarily lose access to the GPG password, you won’t be able to git commit. A temporary workaround is to set

git config commit.gpgsign false

or simply add the --no-gpg-sign option like:

git commit -am "msg" --no-gpg-sign

If not signing as default, sign only certain commits by

git commit -S

Note that’s a capital “S”.

Troubleshooting

Signing subkey expired

If you get gpg: signing failed: No secret key or gpg: skipped "...": No secret key, the signing subkey may have expired. GPG subkeys (encryption, signing) expire independently from the main key.

Check which subkeys are expired:

gpg --list-secret-keys

Look for subkeys marked expired. To extend them:

gpg --edit-key <public_hex>
key 1
expire
1y
save

The key N selects which subkey to extend (1 for first, 2 for second, etc.). Then export the updated key to GitHub.

Password prompt not working (macOS)

On macOS if entering the password on git commit doesn’t work, try:

brew install pinentry-mac

and add to ~/.zshrc:

export GPG_TTY=$TTY

Git SSH over port 443

Certain networks may block traffic on port 22, which causes failure for Git operations like:

ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository.

The solution for this is to at least temporarily configure SSH to use port 443, which is typically open for HTTPS traffic. This can be persistently done by editing the user SSH config file usually located at “/.ssh/config”, here for GitHub, where “/.ssh/github” comes from GitHub SSH key setup.

Likewise for

Host github.com
  User git
  IdentityFile ~/.ssh/github
  Hostname ssh.github.com
  Port 443

Host gitlab.com
  User git
  IdentityFile ~/.ssh/gitlab
  Hostname altssh.gitlab.com
  Port 443

Host bitbucket.org
  User git
  IdentityFile ~/.ssh/atlassian
  Hostname altssh.bitbucket.org
  Port 443

An alternative is to specify the port directly in the Git remote URL like:

git push ssh://user@host:PORT/path/to/repo.git main

For even more extreme cases such as were HTTP Agent blocking is suspected, try environment variable GIT_HTTP_USER_AGENT to mimic a web browser user agent string, for example:

export GIT_HTTP_USER_AGENT="Mozilla/5.0"

# try git commands again

Or specify environment variable GIT_SSH_COMMAND.

SSH post-quantum warning

macOS 26.3 upgraded the OpenSSH client to OpenSSH 10.2, which added a warning about SSH server key exchange with non-post-quantum algorithms. The warning was added in OpenSSH 10.1, but macOS 26.3 is the first macOS release to include it from Apple. The warning is meant to alert users that their SSH server may not be using these newer, more secure kex algorithms.

** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to “store now, decrypt later” attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html

The message will hopefully get the SSH server system admin to upgrade their SSH server to support post-quantum key exchange algorithms, which will provide better security against future quantum computer attacks. The OpenSSH PQ page has more information about the post-quantum key exchange algorithms and how to disable the warning on the client side if necessary. Disable the warning per host so you’re not totally blind to the security of the SSH servers you connect to.

Recursively convert line endings with dos2unix + mac2unix

To recursively convert line endings from DOS \r\n and old macOS \r to Unix \n format in all files recursively, use dos2unix and mac2unix commands. For example, it’s not uncommonn that Matlab .m files shared among groups end up with DOS line endings, which can cause issues across different operating systems. When viewed with “git diff” or similar, files might have ^M characters at the end of lines, indicating DOS or old macOS line endings.

On Unix-like shell, use GNU Find to convert in place all .m files:

find . -type f -name "*.m" -exec dos2unix -e {} + -exec mac2unix -e {} +

Or with PowerShell:

winget install --id=waterlan.dos2unix -e
Get-ChildItem -Recurse -Filter *.m | ForEach-Object {
    dos2unix -e $_.FullName
    mac2unix -e $_.FullName
}

Set Git to use the correct line endings to avoid line ending conflicts in Git repositories.

Windows Git Credential Manager

Git over SSH can use SSH-agent to remember SSH keys for Linux and Windows. For those not using Git over SSH but tiring of typing the Git password, on Windows the Git Credential Manager can fix that situation. The install is small and quick, and to use Git Credential Manager, be sure via

git remote -v

that the connection is https:// and not ssh:// where appropriate. Upon trying to git push or git pull, the Git Credential Manager will appear. It works with 2-factor Authentication as well, storing in Windows Credential Manager. The keys can be deleted from Windows Credential Manager if needed, and / or the Personal Access Token automatically generated can be deleted from GitHub.

Note: If using automatic Git push SSH that would need to be disabled to allow git push to use https so that Git Credential Manager is invoked.

Detect executable file arch

For the simplest execution and best performance, an executable file binary architecture should generally correspond to the CPU architecture of the operating system it runs on. The late 1990s and early 2000s saw a proliferation of CPU architectures including SPARC, PowerPC, DEC Alpha, MIPS, Itanium, and x86. From the late 2000s through about 2020, the dominant CPU architecture for personal computers was x86_64. The 2020s saw the rise of ARM64 across operating systems including Windows on ARM, Apple Silicon, and Linux.

Given the development time and maintenance burdern of supporting multiple CPU architectures, there are in general situations where a user needs to run an executable file on a different CPU architecture than the executable file was built for. It’s a nice practice for program developers to print their native CPU architecture in their program’s about dialog to help users be aware of the CPU architecture of their executable files such that they can seek a native executable if available. For example, a 32-bit x86 executable might run on a 64-bit x86_64 operating system (via API thunking and environment emulation like WoW64), but a 64-bit x86_64 executable generally cannot natively run on a 32-bit x86 operating system.

With some performance overhead and compatibility limitations, executable JIT translation like macOS Rosetta 2, Windows Prism emulation, or Linux FEX emulation can allow executables of one architecture to run on a different CPU architecture. The operating system level translation or emulation development is typically a large investment in software development and optimization, and is not universally available for all architecture combinations. Apple Rosetta 2 translates x86-64 instructions to ARM64 on Apple Silicon, allowing x86-64 executables to run on ARM64 macOS. On Windows, Prism emulation generally allows x86-64 executables to run on ARM64 Windows. On Linux, FEX emulation allows x86-64 executables to run on ARM64 Linux with real-time API call forwarding.

The LIEF library can be used to detect the CPU architecture of Windows executable files from Python.

Meld Git difftool / mergetool

Git users often use Meld to graphically resolve 2-way differences and 3-way merges.

Configure Git to use Meld:

git config --global diff.tool meld
git config --global merge.tool meld

On Windows, Meld can be installed by:

winget install -e --id Meld.Meld

Troubleshooting

If Meld was installed manually and Git can’t find Meld, configure Git to use Meld by setting the path to Meld.exe like:

git config --global mergetool.meld.path "$Env:ProgramFiles/meld/Meld.exe"

On Windows if also using MSYS2, don’t add Meld.exe to environment variable Path as it has libstdc++.dll that conflicts with MSYS2 G++. The symptom is the G++-built executable will segfault silently. To use Meld from Windows Terminal, add a PowerShell alias by editing the PowerShell profile “notepad $profile” and adding the line:

Set-Alias meld "$Env:ProgramFiles/meld/Meld.exe"

Alternatives:

Python for Windows on ARM

Anaconda Python is working toward Windows on ARM support. For now, Anaconda / Miniconda Python work for Windows on ARM via the built-in Prism emulation. To use native ARM64 Python, which could be useful for benchmarking or maximum (best) computing performance, use plain CPython install for ARM64 such as:

winget install Python.Python.3.14

Upon installing and starting, one sees the ARM64 designation in the Python dialogs.

GDL GNU Data Language build

GDL (GNU Data Language) is a free/libre open-source program that runs a good percentage of IDL code. GDL is actively developed and easily installed by:

  • Linux: apt install gnudatalanguage
  • macOS: use weekly gdl-macOS-arm64-standard.dmg. We do this instead of Homebrew because the homebrew/science tap for gnudatalanguage is currently unmaintained.
  • Windows: get the latest release

Building GDL source uses the GDL build script “scripts/build_gdl.sh” to get the prerequisites. If Anaconda Python is present, conda deactivate first to avoid library problems when building GDL.

git clone https://github.com/gnudatalanguage/gdl

cd gdl/

cmake -B build --install-prefix=$HOME/gdl

cmake --build build --parallel

(optional) Check the install. You will see several plots appearing and disappearing automatically during this test, which takes a few minutes.

cmake --test-dir build -V

Install (do not use sudo):

cmake --install build

Do not build on an ExFAT / FAT32 drive, as the build will fail since symbolic links are not allowed on ExFAT / FAT32. If cmake reports libeigen being too old, install LibEigen3 or:

cmake -Bbuild -DEIGEN3=OFF

To use the Linux distro’s older version of GDL, just use /usr/local/bin/gdl or similar, or rename ~/.local/bin/gdl to ~/.local/bin/gdl0.98 or similar.

Troubleshooting build:

  • Runtime search path conflicts: temporarily comment out those paths in ~/.profile (typically from Anaconda Python, libreadline, libhistory, libz, libjpeg.so)
  • Problems with LZMA, try disabling HDF5: cmake -DHDF5=OFF

Clear Pacman database lock

If upon attempting Pacman operations a failure occurs like:

failed to synchronize all databases (unable to lock database)

This may occur if the system was interrupted during a Pacman operation, leaving a lock file that prevents further package management operations. The lock file is located by:

$(pacman-conf DBPath)/db.lck

which is typically “/var/lib/pacman/db.lck”. Check no other Pacman process is running:

ps -ef | grep pacman

Then the Pacman lock file can be removed:

rm $(pacman-conf DBPath)/db.lck