Wilson Mar bio photo

Wilson Mar


Email me Calendar Skype call

LinkedIn Twitter Gitter Instagram Youtube

Github Stackoverflow Pinterest

Sign git commits and tags (for non-repudiation) in GitHub using GPG, Vault, Yubikey, Keybase

US (English)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Cyrillic Russian   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean


This article is a step-by-step tutorial on how to setup and use GPG signatures for Git to sign commits and tags, for non-repudiation. Git tags are associated with releases.

The contribution of this article is the logical ordering of deep-dive concepts presented in a succint way, as a hands-on narrated scenic tour. “PROTIP” flags advice from hard-won experience such as relevant keyboard shortcuts and things to remember, available only here for you.


“If you … want to verify that commits are actually from a trusted source, Git has a few ways to sign and verify work using GPG.” -git-scm.com/show-ref command

Protect Your Git Repositories From Commit Forgery Using Signing*

BONUS: Since we’re using GPG, here are also notes about signing of whole files using GPG.


There are several variations (decisions) regarding the workflow to use:

  • Operating system of local machine (macOS, Windows, Linux flavors)
  • Install a GUI app and/or Command-line program to sign keys
  • Download installer from publisher web page or run package manager (Homebrew, Chocolately)

  • The secret-keeping service (macOS Keychain, GPG, Yubikey, Keybase.io, employer-specified, etc.)
  • Whether to sign every commit or just git tags per release

The steps:

  1. Install apps and programs locally
  2. Set up Git to sign all commits
  3. Add public GPG key to GitHub
  4. List keys
  5. Sign Git commits
  6. Sign Git tags
  7. Import key to GPG on another host

Desired “Self-Serve” Workflow

Here’s the workflow I would like to see. It’s not so much self-service as a tool for administrators. Anyway…

Before someone starts a job/project, a trusted administrator (the boss) specifies on a “self-service” app what should be installed on each worker’s laptop, such as the client utilities which should be installed for his/her specific job based on RBAC (Role-Based Access Control) or Attribute-based Access Control (ABAC) policies.

The app generates the certificate pairs, stores them in Vault, installs them on GitHub, and saves the keys on the worker’s laptop. This provides a more trusted chain than each employee generating their own key pair.

Then all a new working developer needs to do is, on a pre-configured laptop, make a change and do a git tag or add and commit with a tag, then push.

Install client utilities and sign

The alternatives:

Install on macOS GPG-Suite GUI app

Instead of VIDEO: downloading from website and clicking manually:

  1. Install with one command after installing Homebrew:

    brew cask install gpg-suite

    (its previous name was gpgtools, as in the website gpgtools.com)

  2. Pinch 4 fingers together on the Touchpad and scroll around to click on “GPG Keychain” icon:


    NOTE: It’s in “/Applications/GPG Keychain.app”.

    Gen GPG using macOS GPG-Suite

  3. To generated a GPG key pair click “+ New”, then select the Key Type “RSA Sign Only)”.


Install on macOS gnupg2 CLI utility

  1. Open a Terminal. Be at your home user folder.

  2. Execute a Bash script to do the following:

    Alternately, manually install brew (Homebrew)

  3. Install a Git client:

    brew install git
  4. For information about the brew gpg2 install:

    brew info gnupg2

    The response at time of writing:

    gnupg: stable 2.2.21 (bottled)
    GNU Pretty Good Privacy (PGP) package
    /usr/local/Cellar/gnupg/2.2.21 (134 files, 11.2MB) *
      Poured from bottle on 2020-07-09 at 18:44:27
    From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gnupg.rb
    License: GPL-3.0
    ==> Dependencies
    Build: pkg-config ✔
    Required: adns ✔, gettext ✔, gnutls ✔, libassuan ✔, libgcrypt ✔, libgpg-error ✔, libksba ✔, libusb ✔, npth ✔, pinentry ✔
    ==> Analytics
    install: 55,008 (30 days), 120,808 (90 days), 506,457 (365 days)
    install-on-request: 47,841 (30 days), 104,969 (90 days), 428,775 (365 days)
    build-error: 0 (30 days)
  5. Ensure that commands for “gpg” are routed to gpg2:

    alias gpg="gpg2"
    echo -e "\n$(gpg --version | grep gpg)"    # gpg (GnuPG) 2.2.19

    PROTIP: The response shows that the installation is specific to each version of macOS:

    ==> Downloading https://homebrew.bintray.com/bottles/gmp-6.2.0.mojave.bottle.tar.gz

    Linux installers

    Package installers on Linux have other package names:

    • yum install gnupg2 on CentOS/RHEL
    • dnf install gnupg2 on Fedora
    • apt install gnupg on Debian/Ubuntu

  6. On macOS, install gnupg2 for the gpg program:

    In the script, if each utility is found, it is re-installed if the REINSTALL flag is set on, which it is by default.

    if ! command -v gpg >/dev/null; then
       echo "Installing GPG2 for commit signing..."
       brew install gnupg2
       # See https://www.gnupg.org/faq/whats-new-in-2.1.html
       if [[ "${MY_RUNTYPE,,}" == *"upgrade"* ]]; then
          echo "GPG2 upgrading ..."
          gpg --version | grep gpg  # outputs many lines!
          # To avoid response "Error: git not installed" to brew upgrade git
          brew uninstall --ignore-dependencies gpg2
          brew uninstall gnupg2
          # NOTE: This does not remove .gitconfig file entry.
          brew install gnupg2

    Install CLI on Windows

  7. Install Chocolatey if you havent’s already.

  8. Install with one command using Chocolatey:

    choco install gpg2 gnupg -y

    Alternately, install Gpg4win GUI using Chocolatey:

    choco install gpg4win


    PROTIP: The command above creates folder $HOME/.gnupg.

  9. Update or Create ~/.gnupg/gpg.conf

    code "$HOME/.gnupg/gpg.conf"
  10. Remove the comment character # from “use-agent” to enable it:

    # Uncomment within config (or add this line)
    # This tells gpg to use the gpg-agent
  11. Update permissions on your ~/.gnupg Directory:

    chmod 700 ~/.gnupg

    Email address in GitHub

  12. Switch to your GitHub Profile Email page


  13. Identify your “no-reply” public email address, such as “john_doe+github@gmail.com”.

    IMPORTANT: The email specified to GPG should match the email in GitHub.

  14. While in a Terminal with the present working directory at your local repository, configure you valid GitHub user name and email (if you haven’t already). For example:

    git config --global user.name "John Doe"
    git config --global user.email "john_doe@gmail.com"

    PROTIP: Any name and email can be specified in Git. That’s a big reason organizations ask for cryptographically signing commits in GitHub, which requires that the email specified be validated.

Where to store keys


The advantage of using the Keybase app to generate GPG keys is that the keys are stored online at keybase.io, where you’ll be able to retrieve your keys when you don’t have your laptop anymore.

The downside is that it’s possible for Keybase.io to be hacked.

PROTIP: Keybase was acquired by Zoom in 2020. Some are concerned that Zoom will stop support of the product because Zoom only wanted the talent and not fund the free product.

VIDEO explains https://github.com/pstadler/keybase-gpg-github

  1. Go to keybase.io and create an account.

    NOTE: Because Keybase asks for verfification of social media accounts, it may be more comforting for repository owners to know that users went through more hoops to obtain and verify each of their accounts, so the account used is less likely to be a fake. Keybase provides value-added services such as adding encryption around direct messages on Twitter. VIDEO: Keybase also works with the pass utility to manage passwords securely (like Vault).

  2. Install the Keybase app to /Applications/Keybase.app:

    brew cask install keybase
  3. Sign locally out to the Keybase service:

    keybase login

    It takes a few seconds and returns you to the command prompt.

  4. To avoid error message:

    gpg: WARNING: server 'gpg-agent' is older than us (2.2.20 < 2.2.23)
    gpg: Note: Outdated servers may lack important security fixes.
    gpg: Note: Use the command "gpgconf --kill all" to restart them.

    do this:

    gpgconf --kill gpg-agent
  5. Import public keys using Keybase:

    keybase pgp export | gpg --import

    Example response:

    gpg: key 938BBBDEB75FEA21: public key "Wilson Mar <wilsonmar@gmail.com>" imported
    gpg: Total number processed: 1
    gpg:               imported: 1
  6. Get the private key:

    keybase pgp export --secret | gpg --allow-secret-key --import

    If you see this response:

    ▶ ERROR No matching keys found
    gpg: no valid OpenPGP data found.
    gpg: Total number processed: 0

  7. Verify progress:

    gpg --list-secret-keys
  8. Generate a GPG keypair:

    keybase pgp gen --multi

    Example prompts and responses:

    Enter your real name, which will be publicly visible in your new key: Patrick Stadler
    Enter a public email address for your key: patrick.stadler@gmail.com
    Enter another email address (or ≪enter> when done):
    Push an encrypted copy of your new secret key to the Keybase.io server? [Y/n] Y
    ▶ INFO PGP User ID: Patrick Stadler <patrick.stadler@gmail.com> [primary]
    ▶ INFO Generating primary key (4096 bits)
    ▶ INFO Generating encryption subkey (4096 bits)
    ▶ INFO Generated new PGP key:
    ▶ INFO   user: Patrick Stadler <patrick.stadler@gmail.com>
    ▶ INFO   4096-bit RSA key, ID CB86A866E870EE00, created 2016-04-06
    ▶ INFO Exported new key to the local GPG keychain
  9. Skip to list keys.

List GPG keys

  1. List what keys have been signed, meaning secret keys (more selective than the gpg -k command):

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

    --keyid-format LONG requests showing only those keys where both public and private key pair exists. This is becuase both are required to sign commits and tags. If nothing is returned, there are no keys usable for signing.

    PROTIP: This above command can be used often, so added as Bash shell alias (keyboard shortcut) in https://github.com/wilsonmar/git-utilities/blob/master/aliases.sh so that you can instead just type:


    In the response, the first line lists the location where keys are stored (with your own user name instead of “wilson_mar”):


    PROTIP: File pubring.kbx is the Gnupg program’s “Key Ring” file. See https://kb.iu.edu/d/awiu about keyring management commands.

  2. To list all keys:

    gpg --list-keys

    External (GPG Suite) to openpgp.or

    If you’re working on open-source projects, not for Enterprise internal use, you can install the GPG Suite (UI app) or Keybase.io.

    The Suite can be installed as a Homebrew formula “brew cask install gpg-suite” (brew cask install gpgtools no longer exists). The GUI app is installed at “/Applications/GPG Keychain.app”. The first time it runs, this pop-up appears:


    Read about it at GPGTools.org and here.

    The Suite requires to be installed “brew install pinentry-mac”, activated by then entry in file ~/.gnupg/gpg-agent.conf

    pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac
  3. If you are not using a Yubikey, proceed to Generate GPG key pairs.

    Optional Yubikey smart chip

    This is for those who work on multiple machines but must use a single signing key.

    If your laptop’s USB has been locked down, skip this and move on to generate a key.

    git-siging-yubikey-100x100.jpg Instead of storing private keys on a laptop’s hard drive (where they can be hacked by any program running on the computer), security-concious people store their private keys in a separate physical smartcard (OpenGPG card) such as a Yubikey device (one of several).

    PROTIP: If you lose your physical dongle, you’ll need to re-generate all keys.

    Keys written to a card can only be used in combination with a PIN code, so that even if a YubiKey is stolen, a thief would not be able to authenticate directly.

    Each YubiKey is its own unique cardno.

  4. Install software to manage Yubikey (ykman):

    brew install ykman
    brew install yubikey-personalization

    Install of yubikey-personalization issues Warning: ykpers 1.20.0 is already installed and up-to-date.

    QUESTION: How to check for vulnerabilities in the above utilities?

  5. Use a text editor to add inside file ~/.gnupg/gpg.conf “no-tty” so it contains:

  6. Insert your YubiKey and run:

    gpgp --card-status

    If you see these messages:

    gpg: selecting openpgp failed: Operation not supported by device
    gpg: OpenPGP card not available: Operation not supported by device   

    BLOG: continue …


    The response is like this:

    Reader ...........: Yubico Yubikey NEO OTP U2F CCID
    Application ID ...: ID
    Version ..........: 2.0
    Manufacturer .....: Yubico
    Serial number ....: serial
    Name of cardholder: [not set]
    Language prefs ...: [not set]
    Sex ..............: unspecified
    URL of public key : [not set]
    Login data .......: [not set]
    Signature PIN ....: not forced

    References on Yubikey on macOS Git:

    • https://www.isi.edu/~calvin/yubikeyssh.htm
    • https://hugotunius.se/2018/07/13/yubikey-ssh-authentication.html - 13 Jul 2018
    • https://raymondcheng.net/projects/2018/11/25/git-yubikey.html
    • https://evilmartians.com/chronicles/stick-with-security-yubikey-ssh-gnupg-macos

Install GitKraken app and sign

Git UI clients such as GitKraken can generate GPG keys with its UI.

Generate GPG key pairs

### Gen GPG on macOS Terminal

Here are instructions for doing it on a macOS Terminal:

PROTIP: In highly secure organizations, keys are generated by a security department and provided to workers.

  1. Generate another key:

    gpg --gen-key

    --generate-key is the long form of the parameter.

  2. Enter in the series of prompts:

    Real Name: John Doe
    Email address: john-doe+github@gmail.com
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? _

    You’ll have to generate one GPG key for each email address to use if you want to use different email addresses on different projects.

  3. Type “O” (capital or lowercase O) to save the entry.

  4. In response to “Please enter the passphrase to protect your new key”:


    PROTIP: Save you Passphrase in a secure place (such as in Hashicorp Vault), then copy it to paste in the prompt. This tactic is to ensure that you really can retrieve it when you use the key in a future command.

    REMEMBER: Don’t reuse passwords and passphrases.

  5. Re-enter the key.

  6. Press Enter. Sample long-winded response:

    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    gpg: key 62C414BA89BFBE52 marked as ultimately trusted
    gpg: directory '/Users/wilson_mar/.gnupg/openpgp-revocs.d' created
    gpg: revocation certificate stored as '/Users/wilson_mar/.gnupg/openpgp-revocs.d/0BB29E3C5216420CC50ACF8D62C414BA89BFBE52.rev'
    public and secret key created and signed.
    pub   rsa2048 2020-03-01 [SC] [expires: 2022-03-01]
    uid                      Wilson Mar <john_doe+github@gmail.com>
    sub   rsa2048 2020-03-01 [E] [expires: 2022-03-01]

    WARNING: Notice the expiry period is two years from date of creation.

    “rsa2048” is the encryption algorithm used.

  7. List keys to obtain a KeyID.

    RESPONSE=$( gpg --list-secret-keys --keyid-format LONG )

    Parse the RESPONSE:

    gpg: checking the trustdb
    gpg: marginals needed: 3  completes needed: 1  trust model: pgp
    gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
    gpg: next trustdb check due at 2022-03-01
    sec   rsa2048/62C414BA89BFBE52 2020-03-01 [SC] [expires: 2022-03-01]
    uid                 [ultimate] John Doe <john_doe+github@gmail.com>
    ssb   rsa2048/7F2026C2A22F2B37 2020-03-01 [E] [expires: 2022-03-01]
  8. Manually highlight and copy the GPG key ID, which is after “rsa2048/” in the sec section, 62C414BA89BFBE52 in the sample above.

    Alternately, use these Bash script lines to parse the key automatically:

    RESPONSE=$( gpg --list-secret-keys --keyid-format LONG | grep sec )
    # secLine="sec rsa2048/62C414BA89BFBE52 2020-03-01 [SC] [expires: 2022-03-01]"
    GPGKeyID=$( echo ${RESPONSE##*/} | cut -d " " -f 1 )
    echo $GPGKeyID
  9. To set your GPG signing key in Git, substitute the GPG key ID you’d like to use with the value of $GPGKeyID:

    git config --global user.signingkey 62C414BA89BFBE52  #

    No response is expected from the command.

    OPTIONAL: Edit GPG key

    In case you want to fix a typo:

  10. Associate an email (value for field uid) with your GPG key, which Git requires by entering the edit-key mode:

    gpg --edit-key 62C414BA89BFBE52

    This results in this prompt:

  11. Specify “adduid” to enter that mode:

    gpg> adduid
  12. Enter in the series of prompts:

    Real Name: John Doe
    Email address: john-doe+github@gmail.com
    Comment: My Git signing key
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

    The response is like:

    You selected this USER-ID: 
     "John Doe (My Git signing key) <john_doe+github@gmail.com>"
  13. Type “O” (capital or lowercase O) to save the entry.

    Copy and Paste in GitHub

  14. Prepare for pasting of the key generated in this next step by switching to an internet browser of the GitHub page that will receive the public key. After signing in, click your icon at the upper-right, select Settings, SSH and GPG keys:


  15. Click “New GPG key” for a form to accept the contents of the public GPG key, then press command+Tab to switch back to the Terminal.

  16. Print the public GPG key, in ASCII armor format so that they can be sent in a standard messaging format such as email. (Otherwise, the output is in binary format).

    gpg --armor --export 62C414BA89BFBE52 >$HOME/mygitsigning.pub

    PROTIP: Redirecting the command output to a file makes it easier and less error-prone than manually highlighting and copying.

  17. Copy the file’s contents to your operating system Clipboard:

    pbcopy < "$HOME/mygitsigning.pub"

    On Windows, pipe file contents to the clip.exe program built in within C:\Windows\system32 *:

    type mygitsigning.pub | clip

    Alternately, open the file using a text editor, select all file contents, and copy to Clipboard.

    The public key contents should include markers “—–BEGIN PGP PUBLIC KEY BLOCK—–” and “—–END PGP PUBLIC KEY BLOCK—–”.

  18. Switch to the GitHub page opened and click on the input field (so the field border turns blue), then press command+V to paste. Click “Add GPG key”.

    PROTIP: IMPORTANT: If you lost your laptop, immediately remove the SSH and GPG keys associated with that laptop.

    Signing Key

  19. Configure Git to use the program for signing:

    git config --global gpg.program gpg
  20. Configure Git to use your chosen key for signing (“0A46826A” in the example here):

    git config --global user.signingkey 62C414BA89BFBE52
  21. Configure Git to auto-sign ALL Git Tags (called annotations by Git):

    git config --global tag.forceSignAnnotated true

    Sign all commits

    PROTIP: Many say it’s not necessary to sign every commit, just the commit designated by a release.

  22. Configure Git to auto-sign ALL commits on ALL repos:

    git config --global commit.gpgsign true

    PROTIP: It takes a little more time to sign commits.

  23. Each command above adds an entry in file $HOME/.gitconfig created by the Git client:

     name = John Doe
     email = john_doe+github@gmail.com
     signingkey = 62C414BA89BFBE52
     program = gpg2
  24. If you are not using Zsh, edit you ~/.bash_profile to avoid these error messages:

    error: gpg failed to sign the data
    fatal: failed to write commit object

    If using Zsh, edit your ~/.bashrc file.

    Add lines to the bottom of the Shell invocation file:

    test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile
    echo 'export GPG_TTY=$(tty)' >> ~/.profile

    GPG_TTY variable is to avoid errors.

  25. Confirm:

    echo $GPG_TTY
  26. Activate the setting by restarting your Terminal session. If not using Zsh:

    source ~/.bash_profile

Sign Git Commits & merges

This is not recommended by some, but …

  1. To sign a commit, if you didn’t specify signing every time, add command flag capital -S, such as:

    GIT_TRACE=1 git commit -a -S -m "Some message"

    A sample response at time of writing:

    03:48:07.999728 exec-cmd.c:139          trace: resolved executable path from Darwin stack: /Library/Developer/CommandLineTools/usr/bin/git
    03:48:08.000435 exec-cmd.c:236          trace: resolved executable dir: /Library/Developer/CommandLineTools/usr/bin
    03:48:08.001587 git.c:418               trace: built-in: git commit -a -S -m 'Some message'
    03:48:08.017126 run-command.c:643       trace: run_command: gpg2 --status-fd=2 -bsau 62C414BA89BFBE52
    03:48:08.153175 run-command.c:643       trace: run_command: git gc --auto
    03:48:08.156446 exec-cmd.c:139          trace: resolved executable path from Darwin stack: /Library/Developer/CommandLineTools/usr/libexec/git-core/git
    03:48:08.157243 exec-cmd.c:236          trace: resolved executable dir: /Library/Developer/CommandLineTools/usr/libexec/git-core
    03:48:08.158689 git.c:418               trace: built-in: git gc --auto
    [master 71ad705] Some message
     1 file changed, 1 insertion(+)
  2. After push, switch to an internet browser to see a verified badge next to your commits on GitHub online.

    Sign Git Tags


  3. Construct a command to create a Git tag (such as “v1.5.2”) to the current HEAD:

    GIT_TRACE=1 git tag -a -s v1.5.2 -m 'Signed tag 1.5.2'

    -a (annotation) puts the tag in the repository when pushed to GitHub.

    PROTIP: Git tags are like a branch name. in Semantic Versionioning format. See semver.com.

    GIT_TRACE=1 enables tracing. Example output on macOS:

    03:45:46.646487 exec-cmd.c:139          trace: resolved executable path from Darwin stack: /Library/Developer/CommandLineTools/usr/bin/git
    03:45:46.647227 exec-cmd.c:236          trace: resolved executable dir: /Library/Developer/CommandLineTools/usr/bin
    03:45:46.647782 git.c:418               trace: built-in: git tag -a -s v1.5.2 -m 'Signed tag 1.5.2'
    03:45:46.650392 run-command.c:643       trace: run_command: gpg2 --status-fd=2 -bsau 62C414BA89BFBE52

    You are prompted for the GPG key Passphrase.

    Alternately, construct a command to create a Git tag (such as “v1.5.2”) to a previous commit SHA (such as “f3c9f3a”):

    GIT_TRACE-1 git tag v1.5.2 f3c9f3a

    List Git tags

  4. For a list of all version 1 tags:

    git tag -l "v1.*"
  5. See signing info with your latest commit in the git log:

    git log --show-signature -1

    The response would include, for example:

    commit 71ad7059817e609b52b29469e1214a56799b33ef (HEAD -> master)
    gpg: Signature made Mon Mar  2 11:07:39 2020 EST
    gpg:                using RSA key 0BB29E3C5216420CC50ACF8D62C414BA89BFBE51
    gpg: Good signature from "John Doe <john_doe+github@gmail.com>" [ultimate]


    I don’t recommend this, but theoretically you can silence the “you need a Passphrase” prompt by adding in file ~/.gnupg/gpg.conf “batch”. But

    # Connects gpg-agent to the OSX keychain via the brew-installed
    # pinentry program from GPGtools. This is the OSX 'magic sauce',
    # allowing the gpg key's passphrase to be stored in the login
    # keychain, enabling automatic key signing.
    pinentry-program /usr/local/bin/pinentry-mac   

    Push by Tag

    PROTIP: REMEMBER: Tags are push of tags are in addition to content commits.

  6. For convenience (in scripts), push all tags to GitHub:

    git push --tags

    Alternately, specify the new Tag like a branch:

    git push origin v1.5.2

    A sample response:

    Enumerating objects: 1, done.
    Counting objects: 100% (1/1), done.
    Writing objects: 100% (1/1), 540 bytes | 540.00 KiB/s, done.
    Total 1 (delta 0), reused 0 (delta 0)
    To github.com:wilsonmar/git-utilities
            * [new tag]         v1.5.2 -> v1.5.2
  7. See Tags in GitHub under the Code tab, after clicking the release link above GitHub’s colorful line:


    Delete Tags

    Git tags such as “v1.5.2” are meant to be permanently associated with a particular commit through history.

  8. To delete a Tag locally:

    git tag -d v1.5.2

    Alternately, –delete is the long form of the -d parameter.

    Multiple tags can be specified in one command (separated by spaces).

  9. To delete a Tag in remote (GitHub):

    git push origin -d v1.5.2

    Alternately, the really short form replaces -d with a colon (:):

    git push origin :v1.5.2

    Tags in CI/CD

  10. View the list of tags with their full (40 character) hash using the git show-ref command:

    git show-ref --tags

    PROTIP: The above command was added as Bash shell alias (keyboard shortcut) in https://github.com/wilsonmar/git-utilities/blob/master/aliases.sh so that you can instead just type:


    The response is a list of full hashes with the path, such as:

    d4c1e33d1969c8b35938db498a556de25b8c3aa3 refs/tags/v1.5.2
  11. VIDEO: In CI/CD such as Jenkins, get the first among latest tags using the git ref-list command:

    COMMIT_ID=$(git rev-list --tags --date-order | head -1)

    The response is simply a full hash, such as:

  12. Extract the Tag based on the hash using the git show-ref command:

    TAG=$( git show-ref --tags | grep "${COMMIT_ID}" | awk -F / '{print $NF}')

    The variable is used to specify the version in a Docker Build, Push, then Kubernetes apply, such as:

    docker build -t "$DOCKER_ACCOUNT/$DOCKER_REPO:$TAG" .
    sed -e "s/VERSION/$TAG/" /home/centos/deployment.yml >/tmp/deployment.yml
    kubectl apply -f /tmp/deployment.yml
    kubectl get pods -o wide

Encrypting whole files using GPG

GPG can also be used for encryption and decryption of whole files, such as an executable (.exe) file for transmission over email, etc (not related to Git).

There are several ways to verify both the integrity of a file during transmission (as hashing can do) but also provide a way for users to trace authorship.

The steps below describes work with a detached signature where a signature is created in a separate file. We can then provide both the package and the signature file from a trusted source. The user can then verify the package against it. This is like with a hash, but instead of a cleartext signature, the signature is in a “.sig” file which has been encrypted using a private key known only to the file’s owner.

BLOG: Users may want this level of verification for security reasons. Especially if the package handles sensitive information.

  1. Get the signature, such as “62C414BA89BFBE52”.

  2. To create a signed file:

    gpg --detach-sign --sign-with 62C414BA89BFBE52 -o package.sig package.exe

    --detach-sign requests a detached signature to be generated.

    --sign-with precedes the GPG key id to be used to perform signing.

    -o specifies the output file. Traditionally we use either a .sig or a .gpg extension.

  3. For a user to verify integrity of the file:

    gpg --verify package.sig package.exe

Standard signing

Standard signing and clear signing both affects the cleartext file itself. Standard signing is used with encryption. Clear signing wraps the input with plaintext signature.

  1. To sign a plaintext file with your secret key:

    gpg -s textfile
  2. To encrypt a plain text file with the user_id of the recipient’s public key:

    gpg -e -r recipient_userid textfile
  3. To sign a plaintext file with your secret key and have the output readable to people without running GPG first:

    gpg --clearsign textfile
  4. To sign a plaintext file with your secret key, and then encrypt it with the recipient’s public key:

    gpg -se -r recipient_userid
  5. To decrypt a ciphertext file to a clear text outputfile, also checking the signature integrity of a signed file:

    gpg -o outputfile ciphertextfile


This article was the result of consulting several sources of information:

Explanation of gpg program parameters are at: https://www.gnupg.org/documentation/manuals/gnupg/GPG-Input-and-Output.html

As with all things Git, the canonical documentation is at git-scm. Regarding Git signing: https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work




VIDEO: [Git/GitHub] Signing your commits in GitHub – Getting the verified badge on your commits by Raveesh Agarwal


https://juliansimioni.com/blog/troubleshooting-gpg-git-commit-signing quotes https://wiki.gentoo.org/wiki/GnuPG#Changing_pinentry_for_SSH_logins




VIDEO: [Git/GitHub] Signing your commits in GitHub – Getting the verified badge on your commits</a> Jul 7, 2018

A Git Horror Story: repository integrity with signed commits

More on DevOps

This is one of a series on DevOps:

  1. DevOps_2.0
  2. ci-cd (Continuous Integration and Continuous Delivery)
  3. User Stories for DevOps

  4. Git and GitHub vs File Archival
  5. Git Commands and Statuses
  6. Git Commit, Tag, Push
  7. Git Utilities
  8. Data Security GitHub
  9. GitHub API
  10. TFS vs. GitHub

  11. Choices for DevOps Technologies
  12. Java DevOps Workflow
  13. AWS DevOps (CodeCommit, CodePipeline, CodeDeploy)
  14. AWS server deployment options

  15. Cloud services comparisons (across vendors)
  16. Cloud regions (across vendors)
  17. AWS Virtual Private Cloud

  18. Azure Cloud Onramp
  19. Azure Cloud
  20. Azure Cloud Powershell
  21. Bash Windows using Microsoft’s WSL (Windows Subystem for Linux)

  22. Digital Ocean
  23. Cloud Foundry

  24. Packer automation to build Vagrant images
  25. Terraform multi-cloud provisioning automation
  26. Hashicorp Vault and Consul to generate and hold secrets

  27. Powershell Ecosystem
  28. Powershell on MacOS
  29. Powershell Desired System Configuration

  30. Jenkins Server Setup
  31. Jenkins Plug-ins
  32. Jenkins Freestyle jobs
  33. Jenkins2 Pipeline jobs using Groovy code in Jenkinsfile

  34. Docker (Glossary, Ecosystem, Certification)
  35. Make Makefile for Docker
  36. Docker Setup and run Bash shell script
  37. Bash coding
  38. Docker Setup
  39. Dockerize apps
  40. Docker Registry

  41. Maven on MacOSX

  42. Ansible

  43. MySQL Setup

  44. SonarQube static code scan

  45. API Management Microsoft
  46. API Management Amazon

  47. Scenarios for load

More on Security

This is one of a series on Security in DevSecOps:

  1. Git Signing
  2. Hashicorp Vault

  3. WebGoat known insecure PHP app and vulnerability scanners
  4. Test for OWASP using ZAP on the Broken Web App

  5. Encrypt all the things

  6. AWS Security (certification exam)
  7. AWS IAM (Identity and Access Management)

  8. Cyber Security
  9. Security certifications