Skip to content

Latest commit

 

History

History
540 lines (384 loc) · 9.93 KB

File metadata and controls

540 lines (384 loc) · 9.93 KB

Git Configuration File Format

This document describes the Git configuration file format as implemented by this library, based on the official Git documentation.

File Structure

A Git config file consists of sections and variables:

# Comment
[section]
    key = value

[section "subsection"]
    key = value

Syntax Rules

Sections

Sections are defined using square brackets:

[core]
[remote "origin"]
[branch "main"]
  • Simple section: [section]
  • Subsection: [section "subsection"]
  • Section names are case-insensitive
  • Subsection names are case-sensitive

Keys

Keys appear within sections:

[user]
    name = John Doe
    email = [email protected]
  • Key names are case-insensitive
  • Keys can contain alphanumeric characters and dashes
  • Whitespace before = is ignored
  • Keys can appear multiple times (multivars)

Values

Values follow the = sign:

[core]
    editor = vim
    autocrlf = true
    excludesfile = ~/.gitignore_global

Value types:

  • String: Any text (quotes optional unless special characters present)
  • Boolean: true, false, yes, no, on, off, 1, 0
  • Integer: Numeric value (parsed as string by this library)

Special characters in values:

[section]
    # Quoted string with spaces
    key = "value with spaces"
    
    # Escaped characters
    path = "C:\\Users\\Name\\Path"
    
    # Empty value
    emptykey =

Escape Sequences

Within double-quoted strings:

Sequence Meaning
\\ Backslash
\" Double quote
\n Newline
\t Tab
\b Backspace

Example:

[alias]
    log1 = "log --pretty=format:\"%h %s\""

Comments

Comments start with # or ;:

# This is a comment
; This is also a comment

[section]
    key = value  # Inline comments are NOT standard Git behavior

Note: This library may not handle inline comments correctly. Use full-line comments.

Whitespace

  • Leading and trailing whitespace in values is trimmed
  • Internal whitespace in unquoted values is preserved
  • Use quotes to preserve leading/trailing whitespace
[section]
    # These are equivalent:
    key1 = value
    key1=value
    key1  =  value
    
    # These preserve whitespace:
    key2 = "  value with spaces  "

Multi-valued Keys

Some keys can have multiple values:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

Access with:

values, ok := cfg.GetAll("remote.origin.fetch")
// values = ["+refs/heads/*...", "+refs/pull/*..."]

Include Directives

Basic Includes

Include other config files:

[include]
    path = /path/to/other.gitconfig
    path = ~/.gitconfig-extras

Path resolution:

  • Relative paths are resolved from the directory of the current config file
  • ~ expands to user home directory
  • Absolute paths work as expected

Conditional Includes

Include files based on conditions:

[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work

[includeIf "gitdir/i:C:/projects/"]
    path = ~/gitconfig-windows

Supported conditions:

  • gitdir:<pattern> - Include if git directory matches pattern (case-sensitive)
  • gitdir/i:<pattern> - Include if git directory matches pattern (case-insensitive)
  • onbranch:<pattern> - Include if operating on a specific branch

Current limitations:

  • hasconfig:remote.*.url:<pattern> - Not supported

Include Precedence

Later includes override earlier ones:

[user]
    email = [email protected]

[include]
    path = ~/.gitconfig-work  # May override user.email

Settings in included files follow normal override rules.

Key Naming Conventions

Section Hierarchy

Keys use dot notation:

section.key
section.subsection.key

Examples:

[core]
    editor = vim
# Accessed as: core.editor

[remote "origin"]
    url = https://github.com/user/repo.git
# Accessed as: remote.origin.url

[branch "main"]
    remote = origin
# Accessed as: branch.main.remote

Case Sensitivity

  • Section names: Case-insensitive ([Core] = [core])
  • Subsection names: Case-sensitive ([remote "Origin"][remote "origin"])
  • Key names: Case-insensitive (Name = name)

Common Patterns

User Information

[user]
    name = Jane Doe
    email = [email protected]
    signingkey = ABC123

Core Settings

[core]
    editor = vim
    autocrlf = input
    filemode = true
    ignorecase = false
    quotepath = false

Remote Repositories

[remote "origin"]
    url = https://github.com/user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    pushurl = [email protected]:user/repo.git

[remote "upstream"]
    url = https://github.com/project/repo.git
    fetch = +refs/heads/*:refs/remotes/upstream/*

Branch Configuration

[branch "main"]
    remote = origin
    merge = refs/heads/main
    rebase = true

[branch "develop"]
    remote = origin
    merge = refs/heads/develop

Aliases

[alias]
    st = status
    co = checkout
    br = branch
    ci = commit
    unstage = reset HEAD --
    last = log -1 HEAD
    visual = log --graph --oneline --decorate --all

URL Rewrites

[url "[email protected]:"]
    insteadOf = https://github.com/

Note: URL rewrites are not fully supported by this library.

Configuration Scopes

Git supports multiple configuration scopes with defined precedence:

Scope Hierarchy (Highest to Lowest)

  1. Environment variables - GIT_CONFIG_COUNT, GIT_CONFIG_KEY_*, GIT_CONFIG_VALUE_*
  2. Worktree - .git/config.worktree
  3. Local - .git/config (repository-specific)
  4. Global - ~/.gitconfig or $XDG_CONFIG_HOME/git/config (user-specific)
  5. System - /etc/gitconfig (system-wide)

Scope File Locations

Default locations by scope:

Scope Linux/macOS Windows Customizable
System /etc/gitconfig C:\ProgramData\Git\config Yes
Global ~/.gitconfig C:\Users\<user>\.gitconfig Yes
Local .git/config .git\config No
Worktree .git/config.worktree .git\config.worktree No

Library-Specific Behavior

Round-Trip Preservation

This library attempts to preserve the original file structure when writing:

Preserved:

  • Comments (full-line)
  • Blank lines
  • Section order
  • Key order within sections

Not Always Preserved:

  • Exact whitespace formatting (tabs vs spaces)
  • Inline comments
  • Specific indentation

Limitations

Not Supported:

  • Bare boolean values (keys without = sign)
  • Some advanced include conditions (onbranch, hasconfig)
  • URL rewrite patterns
  • Replacing specific instances of multivars

Partial Support:

  • Worktree configurations
  • Some escape sequences
  • Inline comments

Differences from Git

  • Error handling: This library may be more lenient with malformed configs
  • Whitespace: Minor differences in whitespace preservation
  • Extensions: Git supports more conditional include types
  • URL matching: Git's URL insteadOf patterns are not implemented

Validation and Error Handling

Valid Configuration

[section]
    key = value

Common Errors

1. Missing section header:

# ERROR: key without section
key = value

2. Invalid section syntax:

# ERROR: unmatched quotes
[section "subsection]

3. Circular includes:

# config-a
[include]
    path = config-b

# config-b
[include]
    path = config-a  # ERROR: circular reference

4. Invalid escape sequences:

[section]
    # ERROR: unknown escape sequence
    key = "value\x"

Best Practices

  1. Use appropriate scopes

    • User preferences → Global (~/.gitconfig)
    • Repository settings → Local (.git/config)
    • System defaults → System (/etc/gitconfig)
  2. Quote values with special characters

    [section]
        # Good
        path = "C:\\Users\\Name\\Documents"
        
        # May cause issues
        path = C:\Users\Name\Documents
  3. Comment your configuration

    [core]
        # Use vim for commit messages
        editor = vim
  4. Organize related settings

    [user]
        name = Jane Doe
        email = [email protected]
    
    [commit]
        gpgsign = true
    
    [gpg]
        program = gpg2
  5. Use includes for environment-specific settings

    # ~/.gitconfig
    [include]
        path = ~/.gitconfig-personal
    
    [includeIf "gitdir:~/work/"]
        path = ~/.gitconfig-work

Examples

Complete Configuration File

# Global Git configuration
# ~/.gitconfig

[user]
    name = Jane Doe
    email = [email protected]
    signingkey = ABC123DEF456

[core]
    editor = vim
    autocrlf = input
    excludesfile = ~/.gitignore_global
    
[commit]
    gpgsign = true
    verbose = true

[alias]
    st = status -sb
    co = checkout
    br = branch
    ci = commit
    unstage = reset HEAD --
    last = log -1 HEAD
    lg = log --graph --pretty=format:'%h %s'

[push]
    default = current
    followTags = true

[pull]
    rebase = true

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*

[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work

Environment-Specific Configuration

Personal (~/.gitconfig-personal):

[user]
    email = [email protected]

[core]
    editor = code --wait

Work (~/.gitconfig-work):

[user]
    email = [email protected]
    signingkey = WORK123KEY456

[core]
    editor = vim

[commit]
    gpgsign = true

References