29

Here's my situation:

I develop locally on my Mac using MAMP (PHP). My sites are under Git version control, and I point my dev servers to the root of the site under version control on disk.

File structure:
--mysitehere/
---.git/ (.git folder is here versioning everything below)
---src/ (<-- web server root)
----index.php (need the codez here for displaying current git branch)

Anyone have example code that I could use that looks in the .git folder and sees what the current branch is, and output it on the index.php page (and a ruby solution for RoR dev)? This would be super useful when I switch branches, and in my browser when I refresh, I see that I would be on 'master' at the top of the page, or 'your-topic-branch-name-here'.

I'm willing to use a third-party library that accesses git programmatically in PHP, or something that gets the right 'current-branch' variable from a file on disk from within .git.

program247365
  • 3,951
  • 7
  • 33
  • 44
  • 2
    There is a related answer http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch – Ruslan Kabalin Sep 16 '11 at 16:10
  • @Ruslan Kabalin - Yup! That confirms my solution below, which is to look at the HEAD file in the .git/ directory that always contains the current branch. – program247365 Sep 16 '11 at 17:11

10 Answers10

59

This worked for me in PHP, including it in the top of my site:

/**
 * @filename: currentgitbranch.php
 * @usage: Include this file after the '<body>' tag in your project
 * @author Kevin Ridgway 
 */
    $stringfromfile = file('.git/HEAD', FILE_USE_INCLUDE_PATH);

    $firstLine = $stringfromfile[0]; //get the string from the array

    $explodedstring = explode("/", $firstLine, 3); //seperate out by the "/" in the string

    $branchname = $explodedstring[2]; //get the one that is always the branch name

    echo "<div style='clear: both; width: 100%; font-size: 14px; font-family: Helvetica; color: #30121d; background: #bcbf77; padding: 20px; text-align: center;'>Current branch: <span style='color:#fff; font-weight: bold; text-transform: uppercase;'>" . $branchname . "</span></div>"; //show it on the page
DrDol
  • 2,220
  • 2
  • 19
  • 23
program247365
  • 3,951
  • 7
  • 33
  • 44
  • 2
    This doesn't quite work if the branch name includes a "/": most git flow features do. You're going to have to slice the array and then implode it again: $explodedstring = array_slice( $explodedstring , 2 ); $branchname = implode( "/", $explodedstring ); – Giacomo Jul 22 '13 at 17:02
  • 5
    As onliner `` – Florian Grell Oct 17 '13 at 14:05
  • It breaks a lot of environments, where bug/foo or feature/bar is a convention, like Git Flow. The workaround is to limit the explode to 3 items or to manually take what comes after ref: refs/heads/ ... – Dereckson Feb 12 '14 at 06:33
  • If we're going to be kludgy, $gitCurrentBranch = trim(substr(file_get_contents('.git/HEAD'), 16)); as long as .git/HEAD keeps its current format. – Dereckson Feb 12 '14 at 13:40
  • I used: file_get_contents(ROOT . '/.git/HEAD') – mmv_sat Jun 25 '18 at 17:45
  • A file based approach like this works when php is running in environment where git is not installed - eg when running in docker and the files are mounted from the host where git is installed. Running git commands from within php would fail in such environments. This assumes that the mounted path has the .git directory ;) – Chris Rutledge Sep 04 '19 at 14:53
  • 1
    I would suggest to make `$branchname = trim($explodedstring[2]);` the string may contain a newline code at the end – psad Oct 25 '19 at 11:59
  • Works cool, muchos gracias, anyway next time pls, use camelCase for samples, IDE won't scream about unknown words ;) – biesior Nov 02 '20 at 01:09
13

Branch, last commit date and hash

<?php 
    $gitBasePath = '.git'; // e.g in laravel: base_path().'/.git';

    $gitStr = file_get_contents($gitBasePath.'/HEAD');
    $gitBranchName = rtrim(preg_replace("/(.*?\/){2}/", '', $gitStr));                                                                                            
    $gitPathBranch = $gitBasePath.'/refs/heads/'.$gitBranchName;
    $gitHash = file_get_contents($gitPathBranch);
    $gitDate = date(DATE_ATOM, filemtime($gitPathBranch));

    echo "version date: ".$gitDate."<br>branch: ".$gitBranchName."<br> commit: ".$gitHash;                                                       
?>

Example Output:

version date: 2018-10-31T23:52:49+01:00

branch: dev

commit: 2a52054ef38ba4b76d2c14850fa81ceb25847bab

Modification date of file refs/heads/your_branch is (acceptable) approximation of last commit date (especially fo testing/staging environment where we assume that we will deploy fresh commits (no old ones)).

Community
  • 1
  • 1
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
8

I use this function:

protected function getGitBranch()
{
    $shellOutput = [];
    exec('git branch | ' . "grep ' * '", $shellOutput);
    foreach ($shellOutput as $line) {
        if (strpos($line, '* ') !== false) {
            return trim(strtolower(str_replace('* ', '', $line)));
        }
    }
    return null;
}
Ryan
  • 22,332
  • 31
  • 176
  • 357
5

Simple way in PHP:

  • Short hash: $rev = exec('git rev-parse --short HEAD');
  • Full hash: $rev = exec('git rev-parse HEAD');
Sergio Rodrigues
  • 964
  • 9
  • 12
  • 1
    This works as long as the configuration on your local machine will allow you to execute git. I personally ran into problems with that and switched to program247365's answer to solve it. – Jacob Ewing Nov 04 '16 at 15:05
3

To extend on program247365's answer, I've written a helper class for this, which also useful for those using Git Flow.

class GitBranch
{
    /**
     * @var string
     */
    private $branch;

    const MASTER = 'master';
    const DEVELOP = 'develop';

    const HOTFIX = 'hotfix';
    const FEATURE = 'feature';

    /**
     * @param \SplFileObject $gitHeadFile
     */
    public function __construct(\SplFileObject $gitHeadFile)
    {
        $ref = explode("/", $gitHeadFile->current(), 3);

        $this->branch = rtrim($ref[2]);
    }

    /**
     * @param string $dir
     *
     * @return static
     */
    public static function createFromGitRootDir($dir)
    {
        try {
            $gitHeadFile = new \SplFileObject($dir.'/.git/HEAD', 'r');
        } catch (\RuntimeException $e) {
            throw new \RuntimeException(sprintf('Directory "%s" is not a Git repository.', $dir));
        }

        return new static($gitHeadFile);
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->branch;
    }

    /**
     * @return boolean
     */
    public function isBasedOnMaster()
    {
        return $this->getFlowType() === self::HOTFIX || $this->getFlowType() === self::MASTER;
    }

    /**
     * @return boolean
     */
    public function isBasedOnDevelop()
    {
        return $this->getFlowType() === self::FEATURE || $this->getFlowType() === self::DEVELOP;
    }

    /**
     * @return string
     */
    private function getFlowType()
    {
        $name = explode('/', $this->branch);

        return $name[0];
    }
}

You can use it like:

echo GitBranch::createFromGitRootDir(__DIR__)->getName();
Community
  • 1
  • 1
Adam Elsodaney
  • 7,722
  • 6
  • 39
  • 65
  • 2
    This is pretty nice, but the branch names should not be assumed by the fixed constants. Some people use different branch names, and it would be better to be able to pass them into the constructor or use a static config method so the code doesn't need to be rewritten on a per-project or per-repo-structure basis. – mopsyd Dec 24 '17 at 03:40
  • @mopsyd true, but then they would be not be implementing the Git Flow standard. The code here assumes a strict implementation. Perhaps interfaces for these methods would solve the problem of those using their own conventions. – Adam Elsodaney Jan 03 '18 at 22:12
  • The git flow standard does not fit everyone's use case. I prefer it, but there are a number of projects where it is not appropriate, such as those being ported over from a single branch SVN repo. It is not appropriate to enforce opinion about other peoples code, unless they have some tight coupling between each other, which is usually undesirable except in very specific cases. – mopsyd Mar 23 '18 at 20:54
  • This is amazing. Is there a way to add TAGS as well? – Eray T May 26 '22 at 19:02
1

Git Library in PHP (GLIP) is a PHP library for interacting with Git repositories. It does not require Git to be installed on your server and can be found on GitHub.

  • Seems like you must pass in a branch name before you have access to things for glip. Doesn't seem like it will work for what I want, since it has no way of displaying branches, it just expects you to access them directly knowing them by name. That being said I found that in any .git/ repo dir, there is a file called 'HEAD', that has the current branch name in it. I'll probably ending up parsing that directly and will post my answer here when finished. – program247365 Sep 16 '11 at 16:45
0

Quick and dirty option if you're in any subdirectory of the repo:

$dir = __DIR__;
exec( "cd '$dir'; git br", $lines );
$branch = '';
foreach ( $lines as $line ) {
    if ( strpos( $line, '*' ) === 0 ) {
        $branch = ltrim( $line, '* ' );
        break;
    }
}
Pete B
  • 1,709
  • 18
  • 11
0

Gist: https://gist.github.com/reiaguilera/82d164c7211e299d63ac

<?php
// forked from lukeoliff/QuickGit.php

class QuickGit {
  private $version;

  function __construct() {
    exec('git describe --always',$version_mini_hash);
    exec('git rev-list HEAD | wc -l',$version_number);
    exec('git log -1',$line);
    $this->version['short'] = "v1.".trim($version_number[0]).".".$version_mini_hash[0];
    $this->version['full'] = "v1.".trim($version_number[0]).".$version_mini_hash[0] (".str_replace('commit ','',$line[0]).")";
  }

  public function output() {
    return $this->version;
  }

  public function show() {
    echo $this->version;
  }
}
0

The given solutions that read .git/HEAD file causes my pipeline to fail.

Inspired by this question: How to programmatically determine the current checked out Git branch

You can get the git branch name with :

$gitBranchName = trim(shell_exec("git rev-parse --abbrev-ref HEAD"));

Thykof
  • 895
  • 7
  • 9
-1

Why not just this? Its probably only going to be in a template file, once, for a developer's eyes only.

Currently on git branch: <?php echo `git branch --show-current`; ?>

pbgswd
  • 19
  • 3