11

リポジトリに接続し、ファイルのコミット メッセージを追加、コミット、さらにはループするという点で、jGit ファイルの基本を理解することができました。

File gitDir = new File("/Users/myname/Sites/helloworld/.git");

RepositoryBuilder builder = new RepositoryBuilder();
Repository repository;
repository = builder.setGitDir(gitDir).readEnvironment()
        .findGitDir().build();

Git git = new Git(repository);
RevWalk walk = new RevWalk(repository);
RevCommit commit = null;

// Add all files
// AddCommand add = git.add();
// add.addFilepattern(".").call();

// Commit them
// CommitCommand commit = git.commit();
// commit.setMessage("Commiting from java").call();

Iterable<RevCommit> logs = git.log().call();
Iterator<RevCommit> i = logs.iterator();

while (i.hasNext()) {
    commit = walk.parseCommit( i.next() );
    System.out.println( commit.getFullMessage() );

}

次にやりたいことは、1 つのファイルのすべてのコミット メッセージを取得し、その 1 つのファイルを特定の参照/時点に戻すことができるようにすることです。

4

4 に答える 4

10

すべての親コミットに基づいてコミットの変更を見つける方法は次のとおりです

        var tree = new TreeWalk(repository)
        tree.addTree(commit.getTree)
        commit.getParents foreach {
            parent => tree.addTree(parent.getTree)
        }
        tree.setFilter(TreeFilter.ANY_DIFF)

(scalaコード)

TreeFilter.ANY_DIFFは単一のツリーウォーカーに対して機能し、ルートコミットで使用可能なすべての要素を返すことに注意してください。

次に、ツリーを反復処理して、ファイルが指定されたデルタにあるかどうかを確認する必要があります(これは非常に簡単です)。

    while (tree.next)
            if (tree.getDepth == cleanPath.size) {
                // we are at the right level, do what you want
            } else {
                if (tree.isSubtree &&
                    name == cleanPath(tree.getDepth)) {
                    tree.enterSubtree
                }
            }
    }

(cleanPathは純粋なリポジトリパスであり、「/」で分割されます)

次に、そのコードをRevWalk.nextループにラップすると、コミットとコミットによって変更されたファイルが取得されます。

1つのツリーが異なる場合、ANY_DIFFはtrueであるため、ANY_DIFFとは異なるフィルターを使用することをお勧めします。これは、すべての親ツリーと比較してブロブが変更されなかったマージの場合、少し直感に反します。したがって、これがALL_DIFFのコアであり、すべての親ツリーとは異なる要素のみが表示されます。

override def include(walker: TreeWalk): Boolean = {
    val n = walker.getTreeCount();
    if (n == 1) {
        return true;
    }
    val m = walker.getRawMode(0)
    var i = 1
    while (i < n) {
        if (walker.getRawMode(i) == m && walker.idEqual(i, 0)) {
            return false
        }
        i += 1
    }
    true
}

(AnyDiffFilterから派生したscalaコード)

于 2011-05-01T22:37:33.823 に答える
8

だから私はcharlieboyのソリューションを機能させようとしました、そしてそれはほとんどうまくいきました、しかしそれは次の場合に私にとって失敗しました(多分その投稿以来jgitで何かが変わったのですか?)

fileAを追加し、「commit1」としてコミットします。fileBを追加し、「commit2」としてコミットします。

getFileVersionDateList("fileA")

両方commit 1commit 2が見つかりましたが、私が期待していたのはcommit 1

私の解決策は次のとおりです。

List<Commit> commits = new ArrayList<Commit>();

RevWalk revWalk = new RevWalk(repository);
revWalk.setTreeFilter(
        AndTreeFilter.create(
                PathFilterGroup.createFromStrings(<relative path in question>),
                TreeFilter.ANY_DIFF)
);

RevCommit rootCommit = revWalk.parseCommit(repository.resolve(Constants.HEAD));
revWalk.sort(RevSort.COMMIT_TIME_DESC);
revWalk.markStart(rootCommit);

for (RevCommit revCommit : revWalk) {
    commits.add(new GitCommit(getRepository(), revCommit));
}

LogCommandの使用はさらに簡単で、次のようになります。

List<Commit> commitsList = new ArrayList<Commit>();

Git git = new Git(repository);
LogCommand logCommand = git.log()
        .add(git.getRepository().resolve(Constants.HEAD))
        .addPath(<relative path in question>);

for (RevCommit revCommit : logCommand.call()) {
    commitsList.add(new GitCommit(this, revCommit));
}

もちろん、必要に応じてコミット日なども確認します。

于 2012-08-25T00:12:38.660 に答える
2

特定のファイルの履歴を見つけるための git の一般的なアプローチは、リビジョン グラフ (実行中) をたどり、それぞれについて、問題のパスによって参照されるオブジェクト (ブロブまたはツリーのいずれか) をテストすることです。サブツリー全体の履歴を検索します)。したがって、基本的にはリビジョン ウォーカーによるリビジョン セット出力のフィルターとして機能します。

jgitのドキュメントは...まばらなようです。ただし、各 RevCommit に対応する RevTree を取得できる必要があります。必要に応じて、各パス セグメントを順番に最終オブジェクト ID までたどります。

于 2011-01-24T00:13:29.450 に答える
1

araqnid は正しいです。これは、問題のファイルを含むコミットに関連する各日付の日付のリストを取得する方法です...

次に、ファイルの名前とコミットの日付があるため、特定のコミットからファイルを取得できます。以下の2つの方法を参照してください....

注: このコードは .groovy クラスにあるため、Java 用に少し修正する必要があることは間違いありません。

byte[] getAnyPreviousVersionFileBytes(String relativeFilePath, Date date) {

    byte[] bytes = null
    try {

        RevWalk revWalk = new RevWalk(repository)
        ObjectId headId = repository.resolve(Constants.HEAD);
        RevCommit root = revWalk.parseCommit(headId);

        revWalk.sort(RevSort.COMMIT_TIME_DESC);
        revWalk.markStart(root);

        for (RevCommit revCommit: revWalk) {

            // if date matches then walk the tree in this commit
            if (new Date(revCommit.commitTime * 1000L) == date) {

                TreeWalk treeWalk = TreeWalk.forPath(repository, relativeFilePath, revCommit.getTree())

                if (treeWalk != null) {
                    treeWalk.setRecursive(true)
                    CanonicalTreeParser canonicalTreeParser = treeWalk.getTree(0, CanonicalTreeParser)

                    while (!canonicalTreeParser.eof()) {

                        // if the filename matches, we have a match, so set teh byte array to return
                        if (canonicalTreeParser.getEntryPathString() == relativeFilePath) {
                            ObjectLoader objectLoader = repository.open(canonicalTreeParser.getEntryObjectId())
                            bytes = objectLoader.bytes
                        }
                        canonicalTreeParser.next(1)
                    }
                }
            }

        }

    }
    catch (Exception e) {
        throw new JgitException(e)
    }
    return bytes
}

List<Date> getFileVersionDateList(String relativeFilePath) {

    List<Date> versions = new LinkedList<Date>()
    try {

        RevWalk revWalk = new RevWalk(repository)
        ObjectId headId = repository.resolve(Constants.HEAD);
        RevCommit root = revWalk.parseCommit(headId);

        revWalk.sort(RevSort.COMMIT_TIME_DESC);
        revWalk.markStart(root);

        for (RevCommit revCommit: revWalk) {

            TreeWalk treeWalk = TreeWalk.forPath(repository, relativeFilePath, revCommit.getTree())

            if (treeWalk != null) {
                treeWalk.setRecursive(true)
                CanonicalTreeParser canonicalTreeParser = treeWalk.getTree(0, CanonicalTreeParser)

                while (!canonicalTreeParser.eof()) {
                    // if the filename matches, we have a match, so add the date of this commit to the list
                    if (canonicalTreeParser.getEntryPathString() == relativeFilePath) {
                        versions.add(new Date(revCommit.commitTime * 1000L))
                    }
                    canonicalTreeParser.next(1)
                }
            }
        }
    }
    catch (Exception e) {
        throw new JgitException(e)
    }

    return versions
}
于 2011-04-14T10:47:17.487 に答える