ryanxedi / git-info
Read Git branch names and commit hashes using plain PHP
Requires
- php: >=8.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Git Info
Your branch. Your commit. Just PHP.
Read a local repository's branch name and full commit hash in any PHP application. Add a build label to a dashboard, identify a checkout in a CLI tool, or show developers exactly which code is running.
- PHP 8.0+, with zero package dependencies.
- No shell commands or Git executable required at runtime.
- Framework independent, with optional Laravel auto-discovery and a facade.
- Handles nested branch names, packed refs, detached HEAD, worktrees, and submodules.
- Returns clean values or
null, with predictable behaviour when metadata is missing.
Quick start · API · Laravel · Deployment · AI integration guide · Development
Quick start
Install the package:
composer require ryanxedi/git-info
Create example.php in your project root:
<?php require __DIR__ . '/vendor/autoload.php'; use RyanXedi\GitInfo\GitInfo; $git = new GitInfo(__DIR__); echo 'Branch: ' . ($git->branch() ?? 'detached or unavailable') . PHP_EOL; echo 'Commit: ' . ($git->hash() ?? 'unavailable') . PHP_EOL;
Run it with php example.php. No service provider, application container, configuration file, or framework bootstrap is needed.
This package reads the application repository you point it at, rather than the copy of this package installed in
vendor.
Choosing a repository
Pass an absolute path for predictable behaviour in web requests, scheduled jobs, and workers:
use RyanXedi\GitInfo\GitInfo; $git = new GitInfo('/srv/my-application');
A directory inside the repository also works: Git Info searches upwards for the nearest .git entry. Relative paths resolve against the current working directory at construction time.
$git = new GitInfo(__DIR__); // Finds the repository containing this script. $git = new GitInfo(); // Starts from getcwd(), not the script's directory.
You can also pass a bare repository or its Git metadata directory directly.
API
The core class is RyanXedi\GitInfo\GitInfo. Its public API is deliberately small:
public function __construct(?string $path = null); public function branch(): ?string; public function hash(): ?string;
| Method | Result |
|---|---|
branch() |
Full branch name, such as main or feature/payments/fix. Returns null when HEAD is detached or a branch cannot be read. |
hash() |
Full, trimmed commit hash: 40 characters for SHA-1 or 64 for SHA-256. Returns null when no commit can be read. |
| Repository state | branch() |
hash() |
|---|---|---|
| Normal checkout | Branch name | Commit hash |
| Detached HEAD, including a checked-out tag | null |
Commit hash |
| New branch with no commits yet | Branch name | null |
| Missing repository, nonexistent path, or unavailable HEAD | null |
null |
| Readable branch name but missing or invalid commit ref | Branch name | null |
An empty path (new GitInfo('')) throws InvalidArgumentException. Unreadable, missing, or malformed metadata otherwise produces null for the affected value; error messages and filesystem paths are never returned as hashes.
Metadata is read on each call rather than cached. An existing instance can observe updated refs. Separate branch() and hash() calls are independent reads; they are not an atomic snapshot if a checkout changes between them.
A short build label
use RyanXedi\GitInfo\GitInfo; $git = new GitInfo(__DIR__); $hash = $git->hash(); $branch = $git->branch(); $label = ($branch ?? 'detached') . '@' . ($hash === null ? 'unknown' : substr($hash, 0, 8)); // Escape repository-derived text when rendering HTML. echo htmlspecialchars($label, ENT_QUOTES, 'UTF-8');
For JSON APIs, the nullable results can be used directly:
echo json_encode([ 'branch' => $git->branch(), 'commit' => $git->hash(), ]);
Laravel (optional)
Laravel is not installed or required by this package. If your application already uses Laravel, the included adapter supplies automatic service-provider and facade discovery.
The provider binds the core class using the Laravel application's base path. This avoids depending on the process's working directory.
Dependency injection
use RyanXedi\GitInfo\GitInfo; $git = app(GitInfo::class); $branch = $git->branch(); $hash = $git->hash();
The same class can be type-hinted in Laravel controllers and services.
Facade
use RyanXedi\GitInfo\Facades\GitInfo; $branch = GitInfo::branch(); $hash = GitInfo::hash();
The static facade is RyanXedi\GitInfo\Facades\GitInfo. The core class RyanXedi\GitInfo\GitInfo is an instance API; its methods must be called on an object.
Auto-discovery also registers the global GitInfo facade alias. For example, in a Blade view:
@unless (app()->environment('production')) <span>{{ \GitInfo::branch() ?? 'Detached or unavailable' }}</span> @endunless
If your application disables package discovery, register RyanXedi\GitInfo\GitInfoServiceProvider through your application's usual provider configuration. You can then use the imported facade directly; a global alias is optional.
Deployment
Git Info reads local Git metadata. A deployment built from a ZIP, a copied directory, or a container image without .git cannot provide that metadata; both methods return null. Make your UI handle that case.
If the production artifact deliberately excludes .git, capture the commit during your build and expose it through your application's own configuration. Git Info does not automatically read environment variables or contact GitHub or Packagist.
The reader supports Git's standard loose-ref and packed-refs storage, relative and absolute .git pointer files, shared worktree refs via commondir, and SHA-1/SHA-256 hashes. The reftable reference backend is not supported. The reader does not inspect Git objects to verify that a referenced commit exists.
Integration guide for AI coding assistants
Use these facts when integrating this package into another project:
| Integration detail | Exact value or rule |
|---|---|
| Composer package | ryanxedi/git-info |
| Installation | composer require ryanxedi/git-info |
| Minimum PHP | 8.0 |
| Required packages | None |
| Core import | use RyanXedi\GitInfo\GitInfo; |
| Construction | new GitInfo($absoluteRepositoryPath) |
| Default path | Current working directory at construction; searches ancestors |
| Instance methods | branch(): ?string, hash(): ?string |
| Missing data | null; callers choose display fallbacks |
| Detached HEAD | branch() returns null; hash() still returns the commit |
| Laravel facade import | use RyanXedi\GitInfo\Facades\GitInfo; |
| Laravel container binding | RyanXedi\GitInfo\GitInfo::class |
| Git executable / shell access | Not used |
| Network access | Not used |
Suggested integration sequence:
- Install
ryanxedi/git-infowith Composer. - Determine the host application's repository path. Pass it explicitly in plain PHP; use the provided container binding in Laravel.
- Use object methods for the core class, or static methods on the Laravel facade only.
- Handle
nullexplicitly. Keep branch and hash as separate values; a detached checkout can still have a valid hash. - Escape values when rendering HTML. Do not assume a branch name contains only letters and numbers.
- Test both a normal checkout and a deployment without Git metadata.
No framework dependency needs to be added for plain PHP integration. No new API key, GitHub connection, shell command, or service configuration is needed.
Upgrading from the original Laravel package
Version 2.0 introduces these changes:
- PHP 8.0 is the minimum runtime.
new GitInfo()starts from the working directory. Pass your repository path explicitly, or resolve the class through Laravel's container to use the application base path.- Missing values return
nullinstead of diagnostic strings such as.git folder not found. - Detached HEAD has no branch name; its commit hash is still available.
- Hashes no longer include a trailing newline.
- Existing facade and container class names are retained for Laravel applications. Replace the old README's manual alias to the core class with the actual facade, or use auto-discovery.
Development
Clone the repository and run the dependency-free regression suite:
git clone https://github.com/ryanxedi/gitInfo.git
cd gitInfo
php tests/run.php
Or use Composer:
composer install
composer validate --strict
composer test
Tests create and remove isolated temporary repositories; they do not depend on the checkout's branch name. The CI workflow covers PHP 8.0–8.5 and separately checks the optional Laravel adapter against Illuminate 13. The adapter's dependencies are installed into a temporary test project, keeping this package's dependency list empty apart from PHP.
License
MIT.