Skip to content

Instantly share code, notes, and snippets.

@ChristopherA
Last active May 15, 2024 06:43
Show Gist options
  • Save ChristopherA/3bde0d9fe58c406fe283bd8e392b4bff to your computer and use it in GitHub Desktop.
Save ChristopherA/3bde0d9fe58c406fe283bd8e392b4bff to your computer and use it in GitHub Desktop.
Git Environment Variable for Shell Scripts

Git Environment Variable for Shell Scripts

GIT_AUTHOR_IDENT & GIT_COMMITTER_IDENT

The GIT_COMMITTER_IDENT and GIT_AUTHOR_IDENT environment variables allow you to set detailed author and committer information for a git commit in a single environment variable. These variables give you finer control over the identity information attached to commits, which can be particularly useful in automated systems or scripts that manage multiple git operations, or when you need to override both the name, email, and date simultaneously without setting each component individually.

It's worth noting that these variables are less commonly used and are not as well-documented as the individual GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, and GIT_COMMITTER_EMAIL variables.

Format

The format for both GIT_AUTHOR_IDENT and GIT_COMMITTER_IDENT is:

"Name <email> <date>"

Where:

  • Name is the full name of the author or committer.
  • email is the email address.
  • date is the timestamp for the commit. The date should be in UNIX timestamp format followed by a timezone, like 1598467890 -0700.

Example Usage

Let's say you want to commit with the author as John Doe, using the email johndoe@example.com, and the committer as Jane Smith, using the email janesmith@example.com. Here's how you would do it:

GIT_AUTHOR_IDENT="John Doe <johndoe@example.com> $(date +%s -u) +0000" \
GIT_COMMITTER_IDENT="Jane Smith <janesmith@example.com> $(date +%s -u) +0000" \
git commit -S --gpg-sign=~/.ssh/id_sign_ed25519 -m "Signed commit with detailed ident"

Breaking Down the Command

  • date +%s -u generates the current UNIX timestamp in UTC.
  • +0000 explicitly sets the timezone to UTC.
  • -S and --gpg-sign options are used to sign the commit using a GPG key located at ~/.ssh/id_sign_ed25519.

Important Notes

  1. Consistency: Ensure that the GPG_SIGN or git configuration for the signing key matches the committer's email, as GPG keys are often tied to a specific email address.
  2. Security: Be cautious when using these environment variables in scripts, especially when including sensitive information like email addresses.
  3. Debugging: If something goes wrong with setting these variables or the commit doesn't appear as expected, check your shell's handling of environment variables or any typos in the format.

Limitations on user names and email addresses

**User Names:**Git allows users considerable flexibility in choosing usernames, which can include spaces, Unicode characters, and special characters. However, it is advisable to avoid control characters and potentially problematic characters such as colons (:), which may conflict with Git's internal operations or external tools and scripts. Usernames primarily serve identification purposes, not authentication.

Email Addresses: Git requires an email address but is not stringent about its format. While users can technically input any string as an email, for better compatibility and practicality, it's recommended to use a standard email format (e.g., user@example.com). Using incorrect or fabricated email addresses won't hinder Git's basic functions but may affect integration with other systems, such as CI/CD pipelines or collaboration platforms. These systems often rely on valid email addresses to associate commits with specific user accounts.

Additionally, when it comes to verifying commits, GitHub uses the email address to check if the commit is signed with a trusted GPG, SSH, or S/MIME key. A commit is marked as "verified" if GitHub can confirm that the email address associated with the commit signature matches an email in the user’s account that is linked to a public key. This adds an extra layer of security by authenticating the identity of the committer.

Issues with Colons in Git author and committer names and emails

Colons (:) can be problematic in Git names and emails mainly due to how Git internally handles and stores configuration data, as well as how it parses authorship and commit information in certain commands. Here’s a detailed look at why colons are special and the challenges with using them:

Issues with Colons in Git

  1. Configuration Parsing:

    • Git configurations are often stored in a format where colons can be used as delimiters. For example, in the .git/config file, remote URLs, submodules, and other elements use colons as separators or to denote specific sections and their attributes.
  2. Author and Committer Lines:

    • Git commits contain author and committer lines in the format Author: Name <email>, where the colon (:) serves as a delimiter between the key ("Author") and the value ("Name "). If a colon is included in the name or email, it could potentially confuse Git's parsing logic, mistaking parts of the name or email as separate components of the commit metadata.
  3. References and Protocol Handling:

    • Colons are used in Git references and protocols, especially when specifying paths or protocols explicitly, like in file:///path/to/repo or user@host:path/to/repo.git. Misplaced colons can lead to incorrect parsing or handling of paths and URLs.

Escaping Colons

Unfortunately, there is no standard or well-understood method for escaping colons in Git user names and emails that would work universally across different Git operations and integrations. Git does not provide a built-in escaping mechanism for these fields in its commit log data. Attempts to use traditional escape characters (like \ or quotes) typically will not work as expected and can lead to more confusion or errors.

Custom git commit date

You can set a custom date and time for a git commit by using the GIT_AUTHOR_DATE and GIT_COMMITTER_DATE environment variables. These variables allow you to specify the dates for both the authorship and commit separately, if needed. The format for these dates can be either an ISO 8601 date, RFC 2822 date, or a Unix timestamp followed by a space and a timezone offset.

Example:

GIT_AUTHOR_DATE="2024-05-14T12:00:00 +0100" \
GIT_COMMITTER_DATE="2024-05-14T12:00:00 +0100" \
git commit -m "Your commit message"

This command sets both the author and committer dates to May 14, 2024, at 12:00 PM, with a timezone offset of +0100.

In zsh, you can use the strftime command to format the current date and time in the specific format you want. To get the date and time in Universal Time Coordinated (UTC) in the format you're looking for (YYYY-MM-DDTHH:MM:SS +0000), you can use the following command:

strftime '%Y-%m-%dT%H:%M:%S +0000' $(date -u +%s)

Here’s a breakdown of the command:

  • strftime '%Y-%m-%dT%H:%M:%S +0000': This tells strftime to format the date into the specified ISO 8601 format.
  • date -u +%s: This gets the current time in seconds since the Unix epoch (January 1, 1970), in UTC.

You can include this in your script or command line to dynamically set the GIT_AUTHOR_DATE and GIT_COMMITTER_DATE for git commits. For example:

GIT_AUTHOR_DATE=$(strftime '%Y-%m-%dT%H:%M:%S +0000' $(date -u +%s)) \
GIT_COMMITTER_DATE=$(strftime '%Y-%m-%dT%H:%M:%S +0000' $(date -u +%s)) \
git commit -m "Your commit message"

This will ensure that both the author and committer dates are set to the current UTC time when you make the commit, for instance, to not leak the personal data of the of the contributor's time zone .

Precedence:

Git provides a flexible hierarchy for configuration settings, allowing various levels of specificity from environment variables down to local repository settings. Here’s a detailed breakdown of the overriding capabilities, the order of precedence, the special environment variables, and the root paths for global and local configurations.

Order of Precedence

  1. Command Line Options: Highest precedence, directly modify command behavior.
  2. Environment Variables: Overwrite configuration settings for the duration of the command.
  3. Local Configuration (repo/.git/config): Specific to the repository.
  4. Global Configuration (~/.gitconfig or ~/.config/git/config): Applies to all repositories for the current user.
  5. System Configuration (etc/gitconfig): Applies to all users on the system.

List

These environment variables are particularly useful for historical commits or for adjusting dates in a scripted git operation. Each of these variables provides a way to finely control how Git interacts with your local environment, tools, and remote repositories, especially when scripting or integrating with other systems.

  • GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL:

    • These variables specify the author's name and email address for the commit.
  • GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL:

    • These set the committer’s name and email, distinct from the author if necessary.
  • GIT_AUTHOR_DATE: Sets the date used to record when the changes were originally made.

  • GIT_COMMITTER_DATE: Sets the date used to record when the commit was actually made.

  • GIT_GPG_PROGRAM:

    • Specifies the path to the GnuPG executable that Git will use for signing commits. This is useful if you have multiple versions of GnuPG installed or if it's not available in the standard path.
  • GPG_SIGN:

    • This can be set to the key ID you want to use for signing commits (git commit -S) if you don’t want to use the default GPG key.
  • SSH_COMMAND:

    • Useful if you are working with SSH-based operations (not directly related to commit signing but relevant for operations involving remote repositories). It allows specifying a custom command to use when Git needs to connect over SSH, which can include specifying a particular private key.
  • GIT_SSH, GIT_SSH_COMMAND:

    • These variables can specify a custom SSH executable or command to use instead of the default ssh, particularly useful when you need to provide specific SSH options or use an identity file.
  • GIT_CONFIG_COUNT, GIT_CONFIG_KEY_<n>, GIT_CONFIG_VALUE_<n>:

    • These are used to pass multiple configuration values through the environment, which can be useful in scripts.
  • GIT_DIR:

    • Specifies the path to the .git directory. If this is not specified, Git defaults to looking for the repository in the current directory or its parent directories.
  • GIT_WORK_TREE:

    • Defines the path to the working directory. If not specified, the default is the parent directory of the .git directory.
  • GIT_INDEX_FILE:

    • Specifies an alternative index file to use instead of the default .git/index.
  • GIT_OBJECT_DIRECTORY:

    • Specifies the location for new objects when writing them to the database.
  • GIT_ALTERNATE_OBJECT_DIRECTORIES:

    • Used to specify a colon-separated list of paths to alternative object directories, which are used to look up Git objects not found in the primary object store.
  • GIT_CEILING_DIRECTORIES:

    • A colon-separated list of absolute paths. Git will not traverse up past these directories when looking up the .git directory.
  • GIT_COMMITTER_IDENT and GIT_AUTHOR_IDENT:

    • Specify the full author or committer information (respectively), overriding GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE.
  • GIT_TEMPLATE_DIR:

    • Specifies the path to the template directory containing files to copy into the .git directory of a new repository on git init.
  • GIT_TRACE:

    • Used to enable tracing of Git commands, providing insights into how Git commands are executed.
  • GIT_TRACE_PACK_ACCESS:

    • Enables tracing of packfile access, which is useful for debugging and understanding Git's internal behavior.
  • GIT_TRACE_PACKET:

    • Enables detailed tracing of git packet-level operations, useful for debugging network operations.
  • GIT_TRACE_PERFORMANCE:

    • Enables performance tracing to the standard error, providing performance-related data useful in performance tuning.
  • GIT_TRACE_SETUP:

    • Traces setup issues, showing how Git finds its directories and configuration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment