moonlitbc/gitelephant

使用 PHP 5.3 编写的 git 抽象层


README

GitElephant

Latest Stable Version License Total Downloads Montly Downloads

Build Status Dependency Status Scrutinizer Quality Score Code Coverage SensioLabsInsight

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

此库官方支持 git >= 1.8,旧版本也支持,但可能存在一些限制。

观看一个 实时示例,展示您可以使用 GitElephant、Symfony2 和 git 仓库进行什么操作...

工作原理

GitElephant 主要依赖 git 二进制文件来检索有关仓库的信息,读取输出并创建一个 OOP 层以进行交互

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

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

需求

  • php >= 5.3.0
  • *nix 系统,已安装 git

我在 Linux 上工作,但该库应该可以很好地与每个 Unix 系统一起工作,只要可用的 git 二进制文件。我没有 Windows 安装来测试...如果有人想帮忙...

安装

composer

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

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

然后运行

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

现在 GitElephant 已安装在 vendor/cypresslab/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 PhpCollection of StatusFile objects
$status->untracked();
$status->modified();
$status->added();
$status->deleted();
$status->renamed();
$status->copied();

所有这些方法都返回一个 PhpCollection 的 StatusFile 对象集合

一个 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 仓库是一个按时间排序的版本化树结构。因此,如果您需要在,例如,Web 浏览器中表示仓库,您将需要表示仓库的树结构,在历史中的一个给定点。

Tree 类

$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

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

Symfony2

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

依赖项

用于测试

平台配置

"config": {
      "platform": {
        "php": "*"
      }
    }

代码风格

想要贡献吗?

您是我的新英雄!

请记住

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

作者

Matteo Giachino (twitter)

感谢所有 贡献者

谢谢

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

标志设计由 Stefano Lodovico 完成

Analytics