Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Git State Laravel Package

sebastian/git-state

Describe the state of a Git checkout from PHP. Detect origin URL, current branch and commit hash, and whether the working directory is clean; otherwise return the git status output. Useful for build metadata and diagnostics.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Add the package via Composer:

    composer require sebastian/git-state
    

    For development-only use (e.g., testing):

    composer require --dev sebastian/git-state
    
  2. First Use Case: Check Git state in a Laravel controller or command:

    use SebastianBergmann\GitState\Builder;
    
    $gitState = (new Builder)->build();
    
    if (!$gitState) {
        abort(500, 'Git repository not found or missing origin.');
    }
    
    // Log or display Git metadata
    \Log::info('Git State', [
        'branch' => $gitState->branch(),
        'commit' => $gitState->commit(),
        'is_clean' => $gitState->isClean(),
    ]);
    
  3. Where to Look First:

    • Builder class: Core entry point for constructing Git state.
    • GitState object: Contains methods like branch(), commit(), isClean(), and status().
    • Edge Cases: Handle false returns (e.g., missing .git or origin).

Implementation Patterns

Usage Patterns

  1. Artisan Command Integration: Create a custom command to display Git state:

    php artisan make:command GitStatusCommand
    
    // app/Console/Commands/GitStatusCommand.php
    use SebastianBergmann\GitState\Builder;
    
    public function handle()
    {
        $state = (new Builder)->build();
        if (!$state) {
            $this->error('Not a Git repository or missing origin.');
            return;
        }
        $this->info("Branch: {$state->branch()}");
        $this->info("Commit: {$state->commit()}");
        $this->line($state->isClean() ? 'Clean' : 'Dirty: ' . $state->status());
    }
    

    Run with:

    php artisan git:status
    
  2. Exception Handler Integration: Enhance Laravel’s App\Exceptions\Handler to include Git metadata:

    use SebastianBergmann\GitState\Builder;
    use Illuminate\Support\Facades\Log;
    
    public function report(Throwable $exception)
    {
        $gitState = (new Builder)->build();
        Log::error('Exception occurred', [
            'exception' => $exception->getMessage(),
            'git' => $gitState ? [
                'branch' => $gitState->branch(),
                'commit' => $gitState->commit(),
            ] : null,
        ]);
        parent::report($exception);
    }
    
  3. Middleware for Git-Aware Logging: Attach Git state to every request’s log context:

    // app/Http/Middleware/LogGitState.php
    use Closure;
    use SebastianBergmann\GitState\Builder;
    
    public function handle($request, Closure $next)
    {
        $gitState = (new Builder)->build();
        if ($gitState) {
            $request->merge(['git_state' => $gitState]);
        }
        return $next($request);
    }
    

    Register in app/Http/Kernel.php:

    protected $middleware = [
        // ...
        \App\Http\Middleware\LogGitState::class,
    ];
    

    Use in a service:

    $gitState = request()->git_state;
    
  4. CI/CD Guardrails: Fail builds if the working directory is dirty (e.g., in a Laravel Forge hook or GitHub Actions):

    // Example: Laravel Forge deploy hook
    $state = (new \SebastianBergmann\GitState\Builder)->build();
    if (!$state || !$state->isClean()) {
        throw new \RuntimeException('Dirty working directory. Commit changes before deploying.');
    }
    
  5. Dynamic Feature Flags: Enable features based on Git tags or branches:

    $state = (new Builder)->build();
    if ($state && $state->branch() === 'feature/new-ui') {
        Feature::enable('new_ui');
    }
    

Workflows

  1. Caching Git State: Avoid repeated Git process calls by caching results:

    $gitState = Cache::remember('git.state', now()->addHours(1), function () {
        return (new Builder)->build();
    });
    
  2. Fallback for Missing Git: Provide a graceful fallback (e.g., for serverless environments):

    $gitState = (new Builder)->build();
    $state = $gitState ?: new class {
        public function branch() { return 'unknown'; }
        public function commit() { return '0000000'; }
        public function isClean() { return true; }
    };
    
  3. Testing Git State: Mock Git state in tests using Laravel’s service container:

    $this->app->instance(
        \SebastianBergmann\GitState\Builder::class,
        \Mockery::mock(\SebastianBergmann\GitState\Builder::class)
            ->shouldReceive('build')
            ->andReturn(new \SebastianBergmann\GitState\GitState(
                'origin-url',
                'main',
                'abc123',
                true
            ))
    );
    

Integration Tips

  • Laravel Service Container: Bind the Builder to the container for dependency injection:

    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->singleton(\SebastianBergmann\GitState\Builder::class);
    }
    

    Then inject it into classes:

    use SebastianBergmann\GitState\Builder;
    
    public function __construct(private Builder $gitState) {}
    
  • Event Listeners: Trigger actions based on Git state changes (e.g., deploy events):

    // app/Listeners/ValidateGitState.php
    use SebastianBergmann\GitState\Builder;
    
    public function handle()
    {
        $state = (new Builder)->build();
        if (!$state || !$state->isClean()) {
            throw new \RuntimeException('Git validation failed.');
        }
    }
    
  • Environment-Specific Config: Disable Git checks in non-Git environments (e.g., Docker builds):

    if (app()->environment('docker') && !file_exists('.git')) {
        return false;
    }
    

Gotchas and Tips

Pitfalls

  1. false Returns: The package returns false for:

    • Non-Git directories (missing .git).
    • Repos without an origin remote. Always validate the return value:
    $state = (new Builder)->build();
    if (!$state) {
        // Handle error (e.g., log, throw exception, or provide fallback).
    }
    
  2. Git Process Failures: Underlying shell_exec calls may fail silently. Wrap in error handling:

    try {
        $state = (new Builder)->build();
    } catch (\RuntimeException $e) {
        Log::error('Git state check failed: ' . $e->getMessage());
    }
    
  3. Cross-Platform Path Issues: Git paths (e.g., .git/config) may differ on Windows/Linux. Test on both platforms:

    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        // Windows-specific Git path handling.
    }
    
  4. Detached HEAD States: The branch() method may return null or an unexpected value in detached HEAD states. Validate:

    $branch = $state->branch() ?: 'detached HEAD';
    
  5. Submodules or Sparse Checkouts: The package may not handle complex Git configurations (e.g., submodules). Test thoroughly in your environment.

  6. Git Version Incompatibilities: Older Git versions (<2.0) may cause parsing issues. Document requirements in your README.

  7. Performance Overhead: Each build() call spawns a Git process. Cache results aggressively:

    Cache::remember('git.state', now()->addMinutes(5), function () {
        return (new Builder)->build();
    });
    

Debugging Tips

  1. Enable Git Debugging: Temporarily enable verbose Git output by extending the Builder:

    class DebugBuilder extends \SebastianBergmann\GitState\Builder
    {
        protected function executeGitCommand($command)
        {
            return shell_exec('echo "Running: ' . $command . '"; ' . $command);
        }
    }
    
  2. Log Raw Git Output: Log the raw Git commands and outputs for debugging:

    $state = (new Builder)->build();
    if (!$state) {
        Log::debug('Git state build failed. Check logs for raw output.');
        // Log the last Git command executed (if possible).
    }
    
  3. Test Edge Cases: Manually test these scenarios:

    • Empty repo (`git
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport