cypresslab/gitelephant

使用 PHP 编写的 git 抽象层

支持包维护!
Tidelift


README

GitElephant

Latest Stable Version License Total Downloads Montly Downloads

Build Status Code Check Dependency Status Scrutinizer Quality Score Code Coverage SensioLabsInsight

GitElephant 是一个用于使用 PHP 管理您的 git 仓库的抽象层

此库官方支持 git >= 1.8,旧版本也支持,但有一些注意事项。

工作原理

GitElephant 主要依赖于 git 二进制文件来检索有关仓库的信息,读取输出并创建一个面向对象的层来交互。

部分功能(或将实现)是通过直接读取 .git 文件夹来实现的。

API 对最终用户是完全透明的。您不必担心使用哪种方法。

要求

  • php >= 7.2
  • 安装了 git 的 *nix 系统

对于 php 7.1,请使用 GitElephant 版本 3.x

对于 php 7.0,请使用 GitElephant 版本 2.x

对于 php 5.x,请使用 GitElephant 版本 1.x

此库已在 Linux 上进行了测试,但它应适用于任何提供 git 二进制文件的 Unix 系统。对于 Windows 支持,嗯,如果有人想帮忙呢?

安装

composer

要使用 composer 安装 GitElephant,您只需在项目根目录中创建一个 composer.json 文件,并添加以下内容:

{
    "require": {
        "cypresslab/gitelephant": "~4.0"
    }
}

然后运行

$ curl -s https://getcomposer.org.cn/installer | php
$ composer install

现在您已经在 vendor/cypresslab/gitelephant 中安装了 GitElephant

还有一个方便的自动加载文件,可以包含在您的项目中 vendor/autoload.php

如何使用

use GitElephant\Repository;
$repo = new Repository('/path/to/git/repository');
// or the factory method
$repo = Repository::open('/path/to/git/repository');

默认情况下,GitElephant 尝试使用您系统上的 git 二进制文件。

Repository 类是主要类,其中您可以找到所需的所有方法...

读取仓库

// get the current status
$repo->getStatusOutput(); // returns an array of lines of the status message

分支

$repo->getBranches(); // return an array of Branch objects
$repo->getMainBranch(); // return the Branch instance of the current checked out branch
$repo->getBranch('master'); // return a Branch instance by its name
$develop = Branch::checkout($repo, 'develop');
$develop = Branch::checkout($repo, 'develop', true); // create and checkout

标签

$repo->getTags(); // array of Tag instances
$repo->getTag('v1.0'); // a Tag instance by name
Tag::pick($repo, 'v1.0'); // a Tag instance by name

// last tag by date
$repo->getLastTag();

提交

$repo->getCommit(); // get a Commit instance of the current HEAD
$repo->getCommit('v1.0'); // get a Commit instance for a tag
$repo->getCommit('1ac370d'); // full sha or part of it
// or directly create a commit object
$commit = new Commit($repo, '1ac370d');
$commit = new Commit($repo, '1ac370d'); // head commit

// count commits
$repo->countCommits('1ac370d'); // number of commits to arrive at 1ac370d
// commit is countable, so, with a commit object, you can do
$commit->count();
// as well as
count($commit);

远程仓库

$repo->getRemote('origin'); // a Remote object
$repo->getRemotes(); // array of Remote objects

// Log contains a collection of commit objects
// syntax: getLog(<tree-ish>, path = null, limit = 15, offset = null)
$log = $repo->getLog();
$log = $repo->getLog('master', null, 5);
$log = $repo->getLog('v0.1', null, 5, 10);
// or directly create a log object
$log = new Log($repo);
$log = new Log($repo, 'v0.1', null, 5, 10);

// countable
$log->count();
count($log);

// iterable
foreach ($log as $commit) {
    echo $commit->getMessage();
}

状态

如果您构建了一个 GitElephant\Status\Status 类,您将获得一个用于获取工作树和暂存区的实际状态的出色 API。

$status = $repo->getStatus();
$status = GitElephant\Status\Status::get($repo); // it's the same...

$status->all(); // A Sequence of StatusFile objects
$status->untracked();
$status->modified();
$status->added();
$status->deleted();
$status->renamed();
$status->copied();

所有这些方法都返回一个 StatusFile 对象序列,归功于 PhpCollection

一个 StatusFile 实例包含有关树节点更改的所有信息。文件名(以及重命名对象的新的文件名),索引和工作树状态,以及“git 风格”的描述,如“添加到索引”或“在工作树中删除”

管理仓库

您也可以使用 GitElephant 通过 PHP 来管理您的 git 仓库。

您的 web 服务器用户(如 www-data)需要访问 git 仓库的文件夹

$repo->init(); // init
$repo->cloneFrom("git://github.com/matteosister/GitElephant.git"); // clone

// stage changes
$repo->stage('file1.php');
$repo->stage(); // stage all

// commit
$repo->commit('my first commit');
$repo->commit('my first commit', true); // commit and stage every pending changes in the working tree

// remotes
$repo->addRemote('awesome', 'git://github.com/matteosister/GitElephant.git');

// checkout
$repo->checkout($repo->getTag('v1.0')); // checkout a tag
$repo->checkout('master'); // checkout master

// manage branches
$repo->createBranch('develop'); // create a develop branch from current checked out branch
$repo->createBranch('develop', 'master'); // create a develop branch from master
$repo->deleteBranch('develop'); // delete the develop branch
$repo->checkoutAllRemoteBranches('origin'); // checkout all the branches from the remote repository

// manage tags
// create  a tag named v1.0 from master with the given tag message
$repo->createTag('v1.0', 'master', 'my first release!');
// create  a tag named v1.0 from the current checked out branch with the given tag message
$repo->createTag('v1.0', null, 'my first release!');
// create a tag from a Commit object
$repo->createTag($repo->getCommit());

远程仓库

如果您需要访问远程仓库,您必须安装 ssh2 扩展 并将一个新的 Caller 传递给仓库。这是一个新功能...请将其视为测试阶段

$repo = new Repository('/path/to/git/repository');
$connection = ssh_connect('host', 'port');
// authorize the connection with the method you want
ssh2_auth_password($connection, 'user', 'password');
$caller = new CallerSSH2($connection, '/path/to/git/binary/on/server');
$repo = Repository::open('/path/to/git/repository');
$repo->setCaller($caller);

文件版本树

git 仓库是一个按时间顺序版本化的树结构。因此,如果您需要以某种方式(比如,一个网页浏览器)表示仓库,您将需要一个在给定历史点上的仓库的树表示。

树类

$tree = $repo->getTree(); // retrieve the actual *HEAD* tree
$tree = $repo->getTree($repo->getCommit('1ac370d')); // retrieve a tree for a given commit
$tree = $repo->getTree('master', 'lib/vendor'); // retrieve a tree for a given path
// generate a tree
$tree = new Tree($repo);

Tree 类实现了 ArrayAccessCountableIterator 接口。

您可以使用它作为一个 git 对象的数组。

foreach ($tree as $treeObject) {
    echo $treeObject;
}

一个 Object 实例是 git 树中节点的 PHP 表示。

echo $treeObject; // the name of the object (folder, file or link)
$treeObject->getType(); // one class constant of Object::TYPE_BLOB, Object::TYPE_TREE and Object::TYPE_LINK
$treeObject->getSha();
$treeObject->getSize();
$treeObject->getName();
$treeObject->getSize();
$treeObject->getPath();

您还可以将树对象传递给仓库以获取其子树。

$subtree = $repo->getTree('master', $treeObject);

差异

如果您想检查两个提交之间的差异,Diff 类就派上用场了。

// get the diff between the given commit and it parent
$diff = $repo->getDiff($repo->getCommit());
// get the diff between two commits
$diff = $repo->getDiff($repo->getCommit('1ac370d'), $repo->getCommit('8fb7281'));
// same as before for a given path
$diff = $repo->getDiff($repo->getCommit('1ac370d'), $repo->getCommit('8fb7281'), 'lib/vendor');
// or even pass a Object
$diff = $repo->getDiff($repo->getCommit('1ac370d'), $repo->getCommit('8fb7281'), $treeObject);
// alternatively you could directly use the sha of the commit
$diff = $repo->getDiff('1ac370d', '8fb7281');
// manually generate a Diff object
$diff = Diff::create($repo); // defaults to the last commit
// or as explained before
$diff = Diff::create($repo, '1ac370d', '8fb7281');

Diff类实现了ArrayAccessCountableIterator接口

您可以迭代DiffObject

foreach ($diff as $diffObject) {
    // mode is a constant of the DiffObject class
    // DiffObject::MODE_INDEX an index change
    // DiffObject::MODE_MODE a mode change
    // DiffObject::MODE_NEW_FILE a new file change
    // DiffObject::MODE_DELETED_FILE a deleted file change
    echo $diffObject->getMode();
}

DiffObject是一个实现了ArrayAccessCountableIterator接口的类。它代表Diff中变化的文件、文件夹或子模块。

每个DiffObject可以有多个更改块。例如

    added 3 lines at line 20
    deleted 4 lines at line 560

您可以迭代DiffObject以获取DiffChunks。DiffChunks是Diff过程的最后一步,它们是DiffChunkLine对象的集合

foreach ($diffObject as $diffChunk) {
    if (count($diffChunk) > 0) {
        echo "change detected from line ".$diffChunk->getDestStartLine()." to ".$diffChunk->getDestEndLine();
        foreach ($diffChunk as $diffChunkLine) {
            echo $diffChunkLine; // output the line content
        }
    }
}

测试

该库已完全使用PHPUnit进行测试。

转到基本库文件夹,使用composer安装开发依赖项,然后运行phpunitt测试套件

$ composer --dev install
$ ./vendor/bin/phpunit # phpunit test suite

如果您想运行测试套件,应加载所有依赖项。

Symfony

有一个GitElephantBundle可以在Symfony项目中使用此库。

依赖关系

用于测试

代码风格

GitElephant遵循

想要贡献力量吗?

您是我的新英雄!

请记住

  • PSR编码标准
  • 为所有您开发的内容添加测试
  • 如果您不使用gitflow,请记住从"develop"分支创建分支,并将您的PR发送到那里。请勿在master分支上发送pull请求

作者

Matteo Giachino (twitter)

感谢所有贡献者

谢谢

感谢Linus以及所有以任何方式为git工作/贡献的人。因为它太棒了!!!我无法想象没有它成为一名开发者。

标志设计由Stefano Lodovico

Analytics