To get the latest version of Git on CentOS 7, it is possible to compile it directly from source.

Tutorial

This is a quick tutorial showing the necessary steps to install Git from source on CentOS 7. Further documentation is available in the Git Book. This tutorial assumes familiarity with CentOS 7 packages management, source code compilation, and the command-line. Where an instruction applies to a specific shell, the instruction will be shown for both Bash, the default shell on CentOS 7, and fish, the better shell everywhere.[1] To account for two distinct yet equally important use cases, instructions are provided for installing Git for the current user as well as system-wide.

  1. If you aren’t using the DNF package manager yet, grab that.

    sudo yum -y install dnf
  2. Add the EPEL repository for retrieving necessary dependencies.

    sudo dnf -y install \
      https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
  3. Install the build dependencies.

    sudo dnf -y install asciidoc curl-devel dh-autoreconf docbook2X expat-devel \
      gettext-devel openssl-devel perl-devel xmlto zlib-devel
  4. Account the different name of an executable on RPM-based distributions.

    sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
  5. Download the source code of the latest release.

    ➜ wget -L https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.29.2.tar.xz

    Instead of using Wget, you could technically install an older version of Git from the CentOS repositories and use that to fetch the source code for the latest release. The method used here describes where to grab the latest source code releases and lines up with the Git Book’s example.

  6. Download the corresponding signature file.

    ➜ wget -L https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.29.2.tar.sign
  7. Decompress the archive.

    ➜ unxz git-2.29.2.tar.xz
  8. Verify the archive’s signature.

    ➜ gpg --keyserver-options auto-key-retrieve git-2.29.2.tar.sign
    gpg: Signature made Thu 29 Oct 2020 05:14:01 PM CDT using RSA key ID 96AFE6CB
    gpg: requesting key 96AFE6CB from hkp server keys.gnupg.net
    gpg: key 713660A7: public key "Junio C Hamano <gitster@pobox.com>" imported
    gpg: no ultimately trusted keys found
    gpg: Total number processed: 1
    gpg:               imported: 1  (RSA: 1)
    gpg: Good signature from "Junio C Hamano <gitster@pobox.com>"
    gpg:                 aka "Junio C Hamano <jch@google.com>"
    gpg:                 aka "Junio C Hamano <junio@pobox.com>"
    gpg: Note: This key has expired!
    Primary key fingerprint: 96E0 7AF2 5771 9559 80DA  D100 20D0 4E5A 7136 60A7
         Subkey fingerprint: E1F0 36B1 FEE7 221F C778  ECEF B0B5 E886 96AF E6CB

    Here, the option --keyserver-options auto-key-retrieve will automatically import the signing key from the default key server. The signature is valid if Good signature is output. Otherwise, the signature is bad and you must re-download the source archive.

    There are potential privacy concerns when automatically downloading the key this way, as described for the auto-key-retrieve option in gpg2(1).
  9. Extract the source code from the archive.

    tar -xf git-2.29.2.tar
  10. Change into the source directory.

    cd git-2.29.2
  11. Build the configure script.

    ➜ make configure
    GIT_VERSION = 2.29.2
        GEN configure
  12. Configure the build.

    User

    The Freedesktop File-hierarchy specification designates the directory ~/.local/bin for user’s executables. As the specification also notes, this can be problematic for architecture dependent executables, aka anything compiled down to assembly code, like Git here. Unfortunately, the specification provides no method for mediating this problem. Luckily, compilers already have fairly standard methods for describing the system for which code is compiled.[2] We are just going to steal this convention for naming a subdirectory within ~/.local where anything specific to that architecture is installed. Your shell can then handle updating your path to correspond to the architecture you’re running at this time. This should probably be described in detail in another blog post more…​ but that’s the gist.

    fish
    ➜ ./configure --prefix=$HOME/.local/(gcc -dumpmachine)
    Bash
    ➜ ./configure --prefix=$HOME/.local/$(gcc -dumpmachine)
    System-wide
    ➜ ./configure
    The configure script will arrange for installation under the /usr/local directory by default.
  13. Build Git.

    fish
    ➜ make all doc info -j(nproc)
    Bash
    ➜ make all doc info -j$(nproc)
  14. Install Git.

    User
    ➜ make install install-doc install-html install-info
    System-wide
    sudo make install install-doc install-html install-info
  15. Because CentOS doesn’t add /usr/local/bin or ~/.local/*/bin to your PATH by default, add the relevant directory yourself.

    User
    fish
    mkdir -p ~/.config/fish/conf.d; and \
      echo 'set -p fish_user_paths ~/.local/(gcc -dumpmachine)/bin' > \
        ~/.config/fish/conf.d/machine_paths.fish
    ➜ exec fish
    Bash
    echo 'export PATH=$HOME/.local/$(gcc -dumpmachine)/bin:$PATH' >> ~/.bashrc
    ➜ source ~/.bashrc
    System-wide
    1. Ensure that /usr/local/bin is on the PATH in the /etc/environment file used by PAM.

    /etc/environment
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
    1. Log out and back in for the change to take effect.

  16. Change out of the source directory.

    cd ..
  17. Cleanup the source directory and tarball now that are no longer needed.

    rm -rf git-2.29.1 git-2.29.2.tar git-2.29.2.tar.sign

Update

Now that Git has been installed, you can build newer versions of Git directly from Git’s Git repository.

  1. Checkout Git’s source code repository.

    ➜ git clone git://git.kernel.org/pub/scm/git/git.git
    Cloning into 'git'...
    remote: Enumerating objects: 9545, done.
    remote: Counting objects: 100% (9545/9545), done.
    remote: Compressing objects: 100% (722/722), done.
    remote: Total 295465 (delta 9052), reused 9110 (delta 8807), pack-reused 285920
    Receiving objects: 100% (295465/295465), 70.24 MiB | 5.36 MiB/s, done.
    Resolving deltas: 100% (223939/223939), done.

    Keep organized. I recommend installing source code repositories in a directory in your home folder such as ~/Source.

    For reference purposes, you might place source code in /usr/local/src for system-wide installs. Just make sure not to generate any build artifacts in /usr/local/src. You should still do that from within your home directory.

  2. Change into the source directory.

    cd git
  3. Checkout the latest version of git.

    fish
    ➜ git switch --detach (git describe --abbrev=0 --tags)
    HEAD is now at b927c80531 Git 2.29.2
    Bash
    ➜ git switch --detach $(git describe --abbrev=0 --tags)
    HEAD is now at b927c80531 Git 2.29.2
  4. Build the configure script.

    ➜ make configure
    GIT_VERSION = 2.29.2
        GEN configure
  5. Create a build directory to avoid cluttering the sourced directory.

    mkdir build
  6. Change into the build directory.

    cd build
  7. Configure the build.

    User
    fish
    ➜ ../configure --prefix=~/.local/(gcc -dumpmachine)
    Bash
    ➜ ../configure --prefix=~/.local/$(gcc -dumpmachine)
    System-wide
    ➜ ../configure
  8. Build Git.

    fish
    ➜ make all doc info -j(nproc)
    Bash
    ➜ make all doc info -j$(nproc)
  9. Install Git.

    User
    ➜ make install install-doc install-html install-info
    System-wide
    sudo make install install-doc install-html install-info
  10. Change out of the build directory.

    cd ..
  11. Clean up the lingering build artifacts by deleting the build directory.

    rm -rf build

Conclusion

You now have access to a much newer version of Git. Enjoy!


1. It’s not like I’m biased or anything.
2. See Clang’s documentation on Cross Compilation for more info.