{"id":13562751,"url":"https://github.com/matteosister/GitElephant","last_synced_at":"2025-04-03T19:31:24.896Z","repository":{"id":409466,"uuid":"3101180","full_name":"matteosister/GitElephant","owner":"matteosister","description":"An abstraction layer for git written in PHP","archived":false,"fork":false,"pushed_at":"2024-11-26T16:24:54.000Z","size":1843,"stargazers_count":612,"open_issues_count":17,"forks_count":75,"subscribers_count":18,"default_branch":"develop","last_synced_at":"2025-03-23T22:01:44.392Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matteosister.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"tidelift":"packagist/cypresslab/gitelephant"}},"created_at":"2012-01-04T10:27:06.000Z","updated_at":"2025-01-01T23:13:41.000Z","dependencies_parsed_at":"2025-02-23T19:00:32.333Z","dependency_job_id":"9f38ce62-8083-4fe0-9e28-ba7c991a479d","html_url":"https://github.com/matteosister/GitElephant","commit_stats":{"total_commits":748,"total_committers":48,"mean_commits":"15.583333333333334","dds":0.2820855614973262,"last_synced_commit":"de2b2cc905f5a37035fe2f31194fcee71beaad9f"},"previous_names":[],"tags_count":93,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matteosister%2FGitElephant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matteosister%2FGitElephant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matteosister%2FGitElephant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matteosister%2FGitElephant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matteosister","download_url":"https://codeload.github.com/matteosister/GitElephant/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245920551,"owners_count":20694117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T13:01:11.920Z","updated_at":"2025-04-03T19:31:24.563Z","avatar_url":"https://github.com/matteosister.png","language":"PHP","funding_links":["https://tidelift.com/funding/github/packagist/cypresslab/gitelephant"],"categories":["PHP"],"sub_categories":[],"readme":"![GitElephant](https://raw.github.com/matteosister/GitElephant/develop/graphics/gitelephant_600.png)\n\n[![Latest Stable Version](https://poser.pugx.org/cypresslab/GitElephant/v/stable.png)](https://packagist.org/packages/cypresslab/GitElephant) \n[![License](https://poser.pugx.org/cypresslab/gitelephant/license.png)](https://packagist.org/packages/cypresslab/gitelephant) \n[![Total Downloads](https://poser.pugx.org/cypresslab/GitElephant/downloads.png)](https://packagist.org/packages/cypresslab/GitElephant) \n[![Montly Downloads](https://poser.pugx.org/cypresslab/gitelephant/d/monthly.png)](https://packagist.org/packages/cypresslab/gitelephant)\n\n[![Build Status](https://travis-ci.org/matteosister/GitElephant.png?branch=master)](https://travis-ci.org/matteosister/GitElephant) \n[![Code Check](https://github.com/matteosister/GitElephant/workflows/.github/workflows/code_checks.yaml/badge.svg)](.github/workflows/code_checks.yaml)\n[![Dependency Status](https://www.versioneye.com/user/projects/53da38094b3ac86052000019/badge.svg?style=flat)](https://www.versioneye.com/user/projects/53da38094b3ac86052000019) \n[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/matteosister/GitElephant/badges/quality-score.png?s=c7ca8a7c5ea9c64b291f6bcaef27955ed6d8a836)](https://scrutinizer-ci.com/g/matteosister/GitElephant/) \n[![Code Coverage](https://scrutinizer-ci.com/g/matteosister/GitElephant/badges/coverage.png?s=fd7981a4f57fd639912d1a415e3dd92615ddce51)](https://scrutinizer-ci.com/g/matteosister/GitElephant/) \n[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d6da541e-d928-4f70-868a-dd0b6426a7b5/mini.png)](https://insight.sensiolabs.com/projects/d6da541e-d928-4f70-868a-dd0b6426a7b5)\n\nGitElephant is an abstraction layer to manage your git repositories with php\n\nThis library officially supports git \u003e= 1.8, older version are supported as well, but with some caveat.\n\nHow it works\n------------\n\nGitElephant mostly rely on the git binary to retrieve information about the repository, read the output and create an OOP layer to interact with\n\nSome parts are (or will be) implemented by reading directly inside the .git folder\n\nThe api is completely transparent to the end user. You don't have to worry about which method is used.\n\nRequirements\n------------\n\n- php \u003e= `7.2`\n- *nix system with git installed\n\n*For php `7.1`, please use GitElephant version 3.x\n\n*For php `7.0`, please use GitElephant version 2.x\n\n*For php `5.x` please use GitElephant version 1.x\n\nThis library is tested on linux, but it should work well with any unix system, as far as a git binary is available.\nFor windows support, well.. if someone want to help?!\n\nInstallation\n------------\n\n**composer**\n\nTo install GitElephant with composer you simply need to create a *composer.json* in your project root and add:\n\n``` json\n{\n    \"require\": {\n        \"cypresslab/gitelephant\": \"~4.0\"\n    }\n}\n```\n\nThen run\n\n``` bash\n$ curl -s https://getcomposer.org/installer | php\n$ composer install\n```\n\nYou have now GitElephant installed in *vendor/cypresslab/gitelephant*\n\nAnd an handy autoload file to include in you project in *vendor/autoload.php*\n\nHow to use\n----------\n\n```php\nuse GitElephant\\Repository;\n$repo = new Repository('/path/to/git/repository');\n// or the factory method\n$repo = Repository::open('/path/to/git/repository');\n```\n\nBy default GitElephant try to use the git binary on your system.\n\nthe *Repository* class is the main class where you can find every method you need...\n\n**Read repository**\n\n```php\n// get the current status\n$repo-\u003egetStatusOutput(); // returns an array of lines of the status message\n```\n\n*branches*\n\n```php\n$repo-\u003egetBranches(); // return an array of Branch objects\n$repo-\u003egetMainBranch(); // return the Branch instance of the current checked out branch\n$repo-\u003egetBranch('master'); // return a Branch instance by its name\n$develop = Branch::checkout($repo, 'develop');\n$develop = Branch::checkout($repo, 'develop', true); // create and checkout\n```\n\n*tags*\n\n```php\n$repo-\u003egetTags(); // array of Tag instances\n$repo-\u003egetTag('v1.0'); // a Tag instance by name\nTag::pick($repo, 'v1.0'); // a Tag instance by name\n\n// last tag by date\n$repo-\u003egetLastTag();\n```\n\n*commits*\n\n```php\n$repo-\u003egetCommit(); // get a Commit instance of the current HEAD\n$repo-\u003egetCommit('v1.0'); // get a Commit instance for a tag\n$repo-\u003egetCommit('1ac370d'); // full sha or part of it\n// or directly create a commit object\n$commit = new Commit($repo, '1ac370d');\n$commit = new Commit($repo, '1ac370d'); // head commit\n\n// count commits\n$repo-\u003ecountCommits('1ac370d'); // number of commits to arrive at 1ac370d\n// commit is countable, so, with a commit object, you can do\n$commit-\u003ecount();\n// as well as\ncount($commit);\n```\n\n*remotes*\n\n```php\n$repo-\u003egetRemote('origin'); // a Remote object\n$repo-\u003egetRemotes(); // array of Remote objects\n\n// Log contains a collection of commit objects\n// syntax: getLog(\u003ctree-ish\u003e, path = null, limit = 15, offset = null)\n$log = $repo-\u003egetLog();\n$log = $repo-\u003egetLog('master', null, 5);\n$log = $repo-\u003egetLog('v0.1', null, 5, 10);\n// or directly create a log object\n$log = new Log($repo);\n$log = new Log($repo, 'v0.1', null, 5, 10);\n\n// countable\n$log-\u003ecount();\ncount($log);\n\n// iterable\nforeach ($log as $commit) {\n    echo $commit-\u003egetMessage();\n}\n```\n\n*status*\n\nIf you build a GitElephant\\Status\\Status class, you will get a nice api for getting the actual state of the working tree and staging area.\n\n```php\n$status = $repo-\u003egetStatus();\n$status = GitElephant\\Status\\Status::get($repo); // it's the same...\n\n$status-\u003eall(); // A Sequence of StatusFile objects\n$status-\u003euntracked();\n$status-\u003emodified();\n$status-\u003eadded();\n$status-\u003edeleted();\n$status-\u003erenamed();\n$status-\u003ecopied();\n```\n\nall this methods returns a Sequence of StatusFile objects, credit to [PhpCollection](https://github.com/schmittjoh/php-collection)\n\na StatusFile instance has all the information about the tree node changes. File names (and new file names for renamed objects), index and working tree status, and also a \"git style\" description like: *added to index* or *deleted in work tree*\n\n**Manage repository**\n\nYou could also use GitElephant to manage your git repositories via PHP.\n\nYour web server user (like www-data) needs to have access to the folder of the git repository\n\n```php\n$repo-\u003einit(); // init\n$repo-\u003ecloneFrom(\"git://github.com/matteosister/GitElephant.git\"); // clone\n\n// stage changes\n$repo-\u003estage('file1.php');\n$repo-\u003estage(); // stage all\n\n// commit\n$repo-\u003ecommit('my first commit');\n$repo-\u003ecommit('my first commit', true); // commit and stage every pending changes in the working tree\n\n// remotes\n$repo-\u003eaddRemote('awesome', 'git://github.com/matteosister/GitElephant.git');\n\n// checkout\n$repo-\u003echeckout($repo-\u003egetTag('v1.0')); // checkout a tag\n$repo-\u003echeckout('master'); // checkout master\n\n// manage branches\n$repo-\u003ecreateBranch('develop'); // create a develop branch from current checked out branch\n$repo-\u003ecreateBranch('develop', 'master'); // create a develop branch from master\n$repo-\u003edeleteBranch('develop'); // delete the develop branch\n$repo-\u003echeckoutAllRemoteBranches('origin'); // checkout all the branches from the remote repository\n\n// manage tags\n// create  a tag named v1.0 from master with the given tag message\n$repo-\u003ecreateTag('v1.0', 'master', 'my first release!');\n// create  a tag named v1.0 from the current checked out branch with the given tag message\n$repo-\u003ecreateTag('v1.0', null, 'my first release!');\n// create a tag from a Commit object\n$repo-\u003ecreateTag($repo-\u003egetCommit());\n```\n\n**Remote repositories**\n\nIf you need to access remote repository you have to install the [ssh2 extension](http://www.php.net/manual/en/book.ssh2.php) and pass a new *Caller* to the repository. *this is a new feature...consider this in a testing phase*\n\n```php\n$repo = new Repository('/path/to/git/repository');\n$connection = ssh_connect('host', 'port');\n// authorize the connection with the method you want\nssh2_auth_password($connection, 'user', 'password');\n$caller = new CallerSSH2($connection, '/path/to/git/binary/on/server');\n$repo = Repository::open('/path/to/git/repository');\n$repo-\u003esetCaller($caller);\n```\n\nA versioned tree of files\n-------------------------\n\nA git repository is a tree structure versioned in time. So if you need to represent a repository in a, let's say, web browser, you will need\na tree representation of the repository, at a given point in history.\n\n**Tree class**\n\n```php\n$tree = $repo-\u003egetTree(); // retrieve the actual *HEAD* tree\n$tree = $repo-\u003egetTree($repo-\u003egetCommit('1ac370d')); // retrieve a tree for a given commit\n$tree = $repo-\u003egetTree('master', 'lib/vendor'); // retrieve a tree for a given path\n// generate a tree\n$tree = new Tree($repo);\n```\n\nThe Tree class implements *ArrayAccess*, *Countable* and *Iterator* interfaces.\n\nYou can use it as an array of git objects.\n\n```php\nforeach ($tree as $treeObject) {\n    echo $treeObject;\n}\n```\n\nA Object instance is a php representation of a node in a git tree\n\n```php\necho $treeObject; // the name of the object (folder, file or link)\n$treeObject-\u003egetType(); // one class constant of Object::TYPE_BLOB, Object::TYPE_TREE and Object::TYPE_LINK\n$treeObject-\u003egetSha();\n$treeObject-\u003egetSize();\n$treeObject-\u003egetName();\n$treeObject-\u003egetSize();\n$treeObject-\u003egetPath();\n```\n\nYou can also pass a tree object to the repository to get its subtree\n\n```php\n$subtree = $repo-\u003egetTree('master', $treeObject);\n```\n\nDiffs\n-----\n\nIf you want to check a Diff between two commits the Diff class comes in\n\n```php\n// get the diff between the given commit and it parent\n$diff = $repo-\u003egetDiff($repo-\u003egetCommit());\n// get the diff between two commits\n$diff = $repo-\u003egetDiff($repo-\u003egetCommit('1ac370d'), $repo-\u003egetCommit('8fb7281'));\n// same as before for a given path\n$diff = $repo-\u003egetDiff($repo-\u003egetCommit('1ac370d'), $repo-\u003egetCommit('8fb7281'), 'lib/vendor');\n// or even pass a Object\n$diff = $repo-\u003egetDiff($repo-\u003egetCommit('1ac370d'), $repo-\u003egetCommit('8fb7281'), $treeObject);\n// alternatively you could directly use the sha of the commit\n$diff = $repo-\u003egetDiff('1ac370d', '8fb7281');\n// manually generate a Diff object\n$diff = Diff::create($repo); // defaults to the last commit\n// or as explained before\n$diff = Diff::create($repo, '1ac370d', '8fb7281');\n```\n\nThe Diff class implements *ArrayAccess*, *Countable* and *Iterator* interfaces\n\nYou can iterate over DiffObject\n\n```php\nforeach ($diff as $diffObject) {\n    // mode is a constant of the DiffObject class\n    // DiffObject::MODE_INDEX an index change\n    // DiffObject::MODE_MODE a mode change\n    // DiffObject::MODE_NEW_FILE a new file change\n    // DiffObject::MODE_DELETED_FILE a deleted file change\n    echo $diffObject-\u003egetMode();\n}\n```\n\nA DiffObject is a class that implements *ArrayAccess*, *Countable* and *Iterator* interfaces. It represent a file, folder or submodule changed in the Diff.\n\nEvery DiffObject can have multiple chunks of changes. For example:\n\n```\n    added 3 lines at line 20\n    deleted 4 lines at line 560\n```\n\nYou can iterate over DiffObject to get DiffChunks. DiffChunks are the last steps of the Diff process, they are a collection of DiffChunkLine Objects\n\n```php\nforeach ($diffObject as $diffChunk) {\n    if (count($diffChunk) \u003e 0) {\n        echo \"change detected from line \".$diffChunk-\u003egetDestStartLine().\" to \".$diffChunk-\u003egetDestEndLine();\n        foreach ($diffChunk as $diffChunkLine) {\n            echo $diffChunkLine; // output the line content\n        }\n    }\n}\n```\n\nTesting\n-------\n\nThe library is fully tested with PHPUnit.\n\nGo to the base library folder and install the dev dependencies with composer, and then run the phpunitt test suite\n\n``` bash\n$ composer --dev install\n$ ./vendor/bin/phpunit # phpunit test suite\n```\n\nIf you want to run the test suite you should have all the dependencies loaded.\n\nSymfony\n--------\n\nThere is a [GitElephantBundle](https://github.com/matteosister/GitElephantBundle) to use this library inside a Symfony project.\n\nDependencies\n------------\n\n- [symfony/process](https://packagist.org/packages/symfony/process)\n- [symfony/filesystem](https://packagist.org/packages/symfony/filesystem)\n- [symfony/finder](https://packagist.org/packages/symfony/finder)\n- [phpoption/phpoption](https://github.com/schmittjoh/php-option)\n\n*for tests*\n\n- [PHPUnit](https://github.com/sebastianbergmann/phpunit)\n\nCode style\n----------\nGitElephant follows the:\n* [PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)\n* [Extended Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/proposed/extended-coding-style-guide.md)\n* [gitflow](https://github.com/nvie/gitflow)\n\nWant to contribute?\n-------------------\n\n*You are my new hero!*\n\nJust remember:\n\n* PSR coding standards\n* add tests to everything you develop\n* if you don't use gitflow, just remember to branch from \"develop\" and send your PR there. **Please do not send pull requests on the master branch**.\n\nAuthor\n------\n\nMatteo Giachino ([twitter](https://twitter.com/spicy_sake))\n\nMany thanks to all the [contributors](https://github.com/matteosister/GitElephant/graphs/contributors)\n\nThanks\n------\n\nMany thanks to Linus and all those who have worked/contributed in any way to git.\nBecause **it's awesome!!!** I can't imagine being a developer without it.\n\nLogo design by [Stefano Lodovico](http://it.linkedin.com/pub/stefano-lodovico/49/a04/261)\n\n[![Analytics](https://ga-beacon.appspot.com/UA-33181125-2/GitElephant/README?pixel)](https://github.com/igrigorik/ga-beacon)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatteosister%2FGitElephant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatteosister%2FGitElephant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatteosister%2FGitElephant/lists"}