Configuring Git for Drupal

Last updated on
6 December 2022

The following steps will need to be done on each installation of Git you use to contribute to Drupal (home, office, laptop, etc).

Git configuration files (global and per-repo)

Git configuration is stored in a plain-text configuration file called .gitconfig. You have the choice of configuring Git globally or on a per-repository basis (for example, you might need to use one set of configuration for Drupal contributions, and another for Git at your workplace). The global Git configuration file is in your home directory:

  • On Unix-like systems (OS X, Linux, BSD), check ~/.gitconfig
  • On Windows, check C:\Users\[username]\.gitconfig

If the file does not exist yet, you can create it as you would any text file (If the directory does not exist, search harder.) You can also open or create it in your default terminal editor via git using the command:
git config -e --global

If you want to change the configuration for a particular Git repository, you will need to edit the .gitconfigfile at the top level of that repository. Alternatively, you can run this command to open the file in your default terminal editor:

git config -e

To see the current configuration, run this command either at the global or repository level:

git config --list

Git GUI tools

The configuration commands and files mentioned here are appropriate if you are using Git from the command line. If you are using a GUI tool for Git or an IDE that lets you perform Git functions from its GUI, you will need to figure out how to configure your GUI tool in a similar way. Most likely, you will be able to find a "Preferences" or "Options" dialog, under a "Tools" or "Edit" menu, which will allow you to configure Git from within your tool.

Identifying yourself to Git

To be properly credited for your contributions on Drupal.org, you must identify yourself to Git.

To identify yourself, you will need to run two commands either in your home directory or in specific repositories (see section above). Personalized versions of these commands with your details filled in can be found from your Drupal.org user profile page by clicking on Git access, and then locating the Git configuration section of the page. Note that there is an option shown there that will anonymize your email address.

Here are the commands:

git config --global user.name "User name"
git config --global user.email user@example.com

  • It is customary to use your full name for User Name
  • The email address you use when you identify yourself is added to Git’s commit data and creates the link between your commit and your Drupal.org account. So the value of user.email must correspond to an email address for your account. If you would like to keep your email address private, you can identify yourself with the automatically-generated anonymous identifier, which is formatted like an email address, found on the Git access tab of your Drupal.org user profile page.

Configuring Git behavior

To configure Git for use on the command line, add the following configuration directives to the appropriate .gitconfig file.

Always use Unix line-endings in checked out files

[core]
  autocrlf = false
  safecrlf = false

All code and patches will use Unix line-endings (LF) instead of Windows line-endings (CRLF). Unix line-endings are the common standard in open-source projects.

Do not ignore letter casing in filenames on case-insensitive filesystems (like FAT on Windows)

[core]
  ignorecase = false

Note: Even with this setting, Git might not catch some file/directory renames. In those cases, the only workaround is:

git mv original original.tmp
git mv original.tmp Original

Automatically rebase when pulling

[branch]
  autosetuprebase = always

This setting prevents accidental "merge bubbles" (detailed explanation) and is recommended for working on Drupal.org projects. (You still can, and should, merge explicitly when adding large change sets; the purpose is just to prevent unintentional merges when pushing.)

Use color highlighting for diffs and the git log

[color]
  ui = true

Optimize diffs for renamed and copied files

[diff]
  renames = copies

When renaming or copying files, git diff will not show the entire file content for the rename/copy, but merely a single line denoting the rename/copy instead. Subsequent diff hunks in a patch may perform additional changes to the renamed/copied file. This keeps patches small.

Note: git diff/format-patch sometimes may not adhere to renames = copies. The actual limit is not documented, but git only checks for renames/copies up to a similarity of 50-70%. In order to enforce the renames/copies diff behavior, pass an explicit smaller limit:

git diff -M25%

Do not use values lower than 25%, since that will cause git to find false-positive matches on source files; i.e., "copying" a completely different file that just happens to be somewhere in the code-base.

Note: Patches involving renamed and/or copied files will be incompatible with patch file parsers that do not support this diff extension from git.

Define alias properly for applying patches

[alias]
  a = apply --index

git a some.patch will apply the patch and also add any new/renamed/copied/deleted files accordingly to git's index, so you do not forget to add them manually before committing the patch.

Check out new branches from origin by default

[checkout]
  defaultRemote = origin

With Drupal.org's GitLab integration, many developers will have multiple remotes for issue forks. This configuration will allow git to check out branches from origin (the main core repository) by default. There are copy-and-paste commands available on issues for checking out branches within the issue repository remote.

Define the global .gitignore file

You will also need to configure a .gitignore file, which tells Git to ignore certain files and not add them to the Git repository. Start by adding this configuration to the appropriate .gitconfig file (possibly changing the path to the file):

[core]
  excludesfile = ~/.gitignore

Then put the following into the .gitignore file:

# Patch/diff artifacts.
*.patch
*.diff
*.orig
*.rej
interdiff*.txt

# emacs artifacts.
*~
\#*\#

# VI swap file.
*.swp

# Hidden files.
.DS*
.project

# Windows links.
*.lnk

# Temporary files.
tmp*

# Exclude IDE's project directory.
nbproject
.idea

# For Drupal 7, comment the following lines.
vendor
core/node_modules

Thus, git will ignore all .patch, .orig, .rej, .lnk and other files and dirs, everywhere. You can still force-add an ignored file by doing git add -f my.patch, but you usually don't want to do that.

Complete ~/.gitconfig

[core]
  autocrlf = false
  safecrlf = false
  ignorecase = false
  excludesfile = ~/.gitignore
[branch]
  autosetuprebase = always
[diff]
  renames = copies
[color]
  ui = true
[alias]
  a = apply --index
[checkout]
  defaultRemote = origin

Advanced Git configuration

Aliases

git aliases are a powerful way to streamline your most frequent git operations. Read a basic tutorial here. Git Immersion also has a section for aliases.

  • git diffup: Create full patch, interdiff.txt, and commit log in one shot for sandbox patches.

    Applies to:

    • Larger or more complex core patches, which are developed and improved in a sandbox branch.

    Assumptions:

    • You won't push commits upstream before you create a patch for a d.o issue.
    • You want to combine and enforce best practices:
      1. Obviously, providing interdiffs for others.
      2. Doing atomic and clean commits.
      3. Writing proper commit messages.
        (The shortlog can be copied 1:1 into an issue comment.)
    • Your local branch foo tracks the upstream mysandbox/foo branch.

      To configure/enforce this for existing branches:

      git branch --set-upstream foo mysandbox/foo
      

    Alias:

    git config --global alias.diffup '!git log --oneline --first-parent --reverse @{u}... && git diff 8.x... > $1 && git diff @{u} > interdiff.txt && echo'
    

    Explanation:

    1. Outputs the commit messages of all new commits that haven't pushed to upstream yet to the console/stdout. (ready to be copied 1:1 into an issue comment)
    2. Creates a patch file containing all changes from the current branch since it diverged from 8.x.
    3. Creates an interdiff between (old) upstream and the current local branch.

    Usage:

    1. $ git diffup effort.topic.patch
      

      creates:

      • ./effort.topic.patch
      • ./interdiff.txt

      and shows the log; e.g.:

      e20b52b Copied ConfigTest into Drupal\Core\...
      7f20970 Added generic ConfigThingie with ab...
      6b92dac Renamed ConfigThingie::load() into ...
      
    2. After updating the d.o issue, push your local changes into the upstream sandbox branch.
  • git rmbranch: Delete and prune a branch locally + remotely.

    Applies to:

    • Heavy branch users.

    Assumptions:

    • You (and no one else) needs the specified branch anymore.

    Alias:

    git config --global alias.rmbranch '!git branch -d $1 && git push origin --delete'
    

    Explanation:

    1. Deletes the local branch of the given name.
    2. If successful, deletes the remote branch of the given name.

    Usage:

    1. $ git rmbranch myfeature-sun
      

    Benefits:

    • Due to the appearance of "branch" in the alias, your shell might autocomplete branch names.
  • git ac http://patch-url: Download and apply a patch in one command

    Alias:
    In ~/.gitconfig

    [alias]
    # Download and apply a patch.
            a = apply --index
            ac = "!f() { curl $@ | git a; }; f"
    

    Usage:

    git ac http://drupal.org/patch-url.patch
    

Attributes (improved diff function context)

Git comes with support for smartly detecting the proper function context for diffs based on the language. However, it doesn't know by default which file contains which language. To change this, create an attributes file (in $HOME/.config/git/attributes, or $XDG_CONFIG_HOME/git/attributes if that variable is set) with the following contents:

*.engine   diff=php
*.inc      diff=php
*.install  diff=php
*.module   diff=php
*.php      diff=php
*.profile  diff=php
*.test     diff=php
*.theme    diff=php

For more information, see the Git attributes documentation.

Tags

Help improve this page

Page status: No known problems

You can: