PHPackages                             oliver-thiele/deployer-git-drift - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. oliver-thiele/deployer-git-drift

Abandoned → [oliverthiele/deployer-git-drift](/?search=oliverthiele%2Fdeployer-git-drift)Library[Logging &amp; Monitoring](/categories/logging)

oliver-thiele/deployer-git-drift
================================

Deployer recipe: detect and warn about direct server-side file changes before deployment

v0.2.1(1mo ago)05MITPHPPHP &gt;=8.4

Since Jun 30Pushed 1mo agoCompare

[ Source](https://github.com/oliverthiele/deployer-git-drift)[ Packagist](https://packagist.org/packages/oliver-thiele/deployer-git-drift)[ RSS](/packages/oliver-thiele-deployer-git-drift/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (5)Versions (10)Used By (0)

deployer-git-drift — Detect direct server-side file changes before deployment
=============================================================================

[](#deployer-git-drift--detect-direct-server-side-file-changes-before-deployment)

Deployer recipe that detects and warns about files modified directly on the server (via FTP, SFTP, or SSH) before they are silently overwritten by the next deployment.

[![Packagist Version](https://camo.githubusercontent.com/de3e07cfea0d5624a69c93b829063bcabe6ed16ff65b58fd1d2a3ca8c2e4776c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6f6c69766572746869656c652f6465706c6f7965722d6769742d64726966742e737667)](https://packagist.org/packages/oliverthiele/deployer-git-drift)[![PHP](https://camo.githubusercontent.com/6351fd5555b718474455aae297824e52365e7d987048e9efafd88dfbf6b334fe/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f6f6c69766572746869656c652f6465706c6f7965722d6769742d64726966742f7068702e737667)](https://php.net/)[![License](https://camo.githubusercontent.com/e06b792fe9f2ec5bc84d971afeeffb46d9eb8e608e21debea1f2812dd44ce6a3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6f6c69766572746869656c652f6465706c6f7965722d6769742d64726966742e737667)](LICENSE)[![Changelog](https://camo.githubusercontent.com/6bc02a7bc61afc1cb3faaa53420df6d904b9940d7f3e2e11a463e1fdbb3cd52d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4368616e67656c6f672d4348414e47454c4f472e6d642d626c75652e737667)](CHANGELOG.md)

> **Pre-1.0** — This package is under active development. Task names and configuration keys may still change before v1.0. Pin to an exact version and review the [CHANGELOG](CHANGELOG.md) before upgrading.

The Problem
-----------

[](#the-problem)

Deployer uses an atomic symlink swap for zero-downtime deployments. This means there is no Git repository on the production server — only the deployed files exist. When someone modifies files directly on the server (editing a config file, quick-fixing a bug via FTP, uploading an asset), those changes are invisible. The next deployment silently overwrites them.

This recipe solves the problem by:

1. Initializing a shallow Git repository in each release directory after deployment
2. Checking for file changes in the current release before the next deployment starts
3. Warning the developer and requiring explicit confirmation before overwriting

Requirements
------------

[](#requirements)

- PHP &gt;= 8.4
- Deployer &gt;= 7.0
- Git installed on the remote server

Installation
------------

[](#installation)

```
composer require --dev oliverthiele/deployer-git-drift
```

Usage
-----

[](#usage)

In your `deploy.php`:

```
require 'recipe/common.php';
require __DIR__ . '/vendor/oliverthiele/deployer-git-drift/src/GitDrift.php';

// Hook into the deployment flow
after('deploy:symlink', 'git-drift:init');
before('deploy:vendors', 'git-drift:check');
```

Hooks are opt-in by design — the recipe registers tasks only, not automatic hooks.

Configuration
-------------

[](#configuration)

```
// Always abort when drift is detected (default: false — ask interactively)
set('git_drift_abort_on_drift', true);

// Ignore paths that are expected to differ from the Git state
// Typical candidates: generated files, caches, installed dependencies —
// NOT shared_dirs/shared_files, those are handled automatically (see below)
set('git_drift_ignore_paths', [
    'vendor/',
    'node_modules/',
    'var/',
]);

// Additional tracked files that are expected to differ or be rewritten on the
// server (e.g. rewrite rules regenerated by an install routine)
set('git_drift_skip_worktree_paths', [
    'public/.htaccess',
]);
```

Available Tasks
---------------

[](#available-tasks)

TaskDescription`git-drift:init`Initialize Git tracking in the release directory after deployment`git-drift:check`Check for drift before deployment — warns or aborts`git-drift:status`Show drift status without deployingRun the status check manually at any time:

```
dep git-drift:status production
```

Example Output
--------------

[](#example-output)

When drift is detected:

```
⚠ Server drift detected:

 public/index.php | 5 +++--
 config/system/settings.php | 12 ++++++++----

Untracked files added on server:
public/fileadmin/direct-upload.zip

These changes were made directly on the server.
They will be LOST after this deployment.

Continue deployment and discard changes? [y/N]

```

How it works
------------

[](#how-it-works)

After each deployment, `git-drift:init` runs `git init` in the release directory, fetches the deployed branch with `--depth=1`, and sets `FETCH_HEAD` as the baseline via `git reset`. Any subsequent server-side file modifications will appear as changes relative to this baseline.

On the very first deployment after adding this recipe, there is no previous release to compare against, so `git-drift:check` skips with a notice instead of checking anything. Drift detection becomes active starting with the deployment after that.

Paths listed in `git_drift_ignore_paths` are written to `.git/info/exclude` (local gitignore, does not modify project files) so generated, untracked directories are excluded from drift detection.

### Shared directories and export-ignored files

[](#shared-directories-and-export-ignored-files)

Deployer replaces `shared_dirs`/`shared_files` paths with symlinks into `shared/`, so a tracked file underneath one (e.g. a `.gitkeep` placeholder in a shared uploads directory) will always differ from its Git blob. Files marked `export-ignore` in `.gitattributes` are absent from the deployed release entirely and would otherwise look permanently "deleted". Both cases are detected automatically — from Deployer's own `shared_dirs`/`shared_files` config and from a `git archive` comparison — and marked with Git's `--skip-worktree` bit, so they never show up as drift. The shared symlinks themselves are also appended to `.git/info/exclude` automatically, the same file `git_drift_ignore_paths` writes to. No project-specific configuration is needed for either case.

Use `git_drift_skip_worktree_paths` only for tracked files outside of shared dirs that are still expected to be rewritten on the server, such as `.htaccess` rules regenerated by an install routine.

Development
-----------

[](#development)

The skip-worktree decision logic lives in `GitDriftIndexPlanner`, a pure class with no Git or Deployer dependency, so it is covered by unit tests without a real repository.

```
ddev composer install
ddev exec vendor/bin/phpunit
ddev exec vendor/bin/phpstan analyse
ddev exec vendor/bin/php-cs-fixer fix --dry-run --diff
```

License
-------

[](#license)

MIT — Oliver Thiele

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance91

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

8

Last Release

44d ago

PHP version history (2 changes)v0.1.0-alpha1PHP &gt;=8.2

v0.1.4-alpha5PHP &gt;=8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5030298?v=4)[Oliver Thiele](/maintainers/oliverthiele)[@oliverthiele](https://github.com/oliverthiele)

---

Top Contributors

[![oliverthiele](https://avatars.githubusercontent.com/u/5030298?v=4)](https://github.com/oliverthiele "oliverthiele (20 commits)")

---

Tags

monitoringservergitdeploymentdeployerdrift

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/oliver-thiele-deployer-git-drift/health.svg)

```
[![Health](https://phpackages.com/badges/oliver-thiele-deployer-git-drift/health.svg)](https://phpackages.com/packages/oliver-thiele-deployer-git-drift)
```

###  Alternatives

[rollbar/rollbar

Monitors errors and exceptions and reports them to Rollbar

33725.2M90](/packages/rollbar-rollbar)[datadog/php-datadogstatsd

An extremely simple PHP datadogstatsd client

19228.2M16](/packages/datadog-php-datadogstatsd)[rollbar/rollbar-laravel

Rollbar error monitoring integration for Laravel projects

14111.1M11](/packages/rollbar-rollbar-laravel)[ohdearapp/ohdear-php-sdk

An SDK to easily work with the Oh Dear API

743.1M18](/packages/ohdearapp-ohdear-php-sdk)[inspector-apm/inspector-php

Inspector monitoring for PHP applications.

353.2M34](/packages/inspector-apm-inspector-php)[slickdeals/statsd

a PHP client for statsd

275.1M15](/packages/slickdeals-statsd)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
