Git中AuthorDate和CommitDate的区别以及由此引起的JGit使用时造成的Bug

这个坑,多少让人觉得有点无语。其实很早就注意到,Git中一次Commit对应两个时间的,但是也没仔细看JGit中的时间对应的是哪个时间。这里我们以这个Repo为例:https://git-wip-us.apache.org/repos/asf/wicket.git

对于这个Repo而言,如果我在命令行中输入:

git show ca03c252b5745bdccfb7c8cdffcc705846593ec1

那么将得到下面的一些输出:

commit ca03c252b5745bdccfb7c8cdffcc705846593ec1
Author: Sven Meier <svenmeier@apache.org>
Date:   Mon Jun 25 17:19:41 2018 +0200

那这个时间到底是哪一个时间呢,从这里实际上看不太出来。如果我们在命令行中输入:

git log ca03c252b5745bdccfb7c8cdffcc705846593ec1

那么得到的输出和上面相同,只不过后面还有更多的commit信息。只有当我们输入:

git show --pretty=fuller ca03c252b5745bdccfb7c8cdffcc705846593ec1

那么这时候的输出变成了:

commit ca03c252b5745bdccfb7c8cdffcc705846593ec1
Author:     Sven Meier <svenmeier@apache.org>
AuthorDate: Mon Jun 25 17:19:41 2018 +0200
Commit:     Sven Meier <svenmeier@apache.org>
CommitDate: Tue Mar 19 11:53:23 2019 +0100

所以说原来之前输出的Date一直是AuthorDate!
这个确实有点坑啊,而且这个commit也挺奇葩,这两个日期差了这么多!

这种区别就导致了有时候我们拿不到想要的时间信息,从而导致时间匹配和过滤上出错,例如下面这段Java代码用了JGit来获取这个commit对应的时间:

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;

public class Test {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		String repo_path="%wicket这个Repo的本地目录%";
		FileRepositoryBuilder builder = new FileRepositoryBuilder();
		builder.setMustExist(true);
		builder.addCeilingDirectory(new File(repo_path));
		builder.findGitDir(new File(repo_path));
		
		String versionCommit="ca03c252b5745bdccfb7c8cdffcc705846593ec1";
		
		Repository repo;
		repo = builder.build();
		RevWalk walk = new RevWalk(repo);
		ObjectId versionId=repo.resolve(versionCommit);
		RevCommit verCommit=walk.parseCommit(versionId);
		
		System.out.println(verCommit.getCommitTime());
	    Date revTime =new Date((long)verCommit.getCommitTime()*1000);
	    SimpleDateFormat time = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
		String TimeString = time.format(revTime);
		System.out.println();
		System.out.println("This commit time:");
		System.out.println(TimeString);
		
		PersonIdent authorIdent = verCommit.getAuthorIdent();
		Date authorDate = authorIdent.getWhen();
		String authorDateTimeString = time.format(authorDate);
		System.out.println();
		System.out.println("This commit time:");
		System.out.println(authorDateTimeString);
	}
}

另外吐槽一下,getCommitTime返回的是个int的数值,表示从基准时间到现在的秒数。但下面的getWhen返回的是一个Date,这个统一起来很难么??如果我们运行上面的Java的代码,得到的就是:

1552992803

This commit time:
2019-03-19 03:53:23

This commit time:
2018-06-25 08:19:41

也就是说我们用getWhen才能得到和git show,git log中显示的同样的时间。这也太坑了吧!!我估计不止我一个人会遇到这种莫名其妙的问题:上面这段代码也是参考了这里:https://stackoverflow.com/questions/12608610/how-do-you-get-the-author-date-and-commit-date-from-a-jgit-revcommit

至于AuthorDate和CommitDate的区别,请大家参考这里:https://stackoverflow.com/questions/11856983/why-git-authordate-is-different-from-commitdate

另外,如果我用pydriller这个Python库:https://github.com/ishepard/pydriller,那么需要写的代码会少很多(这里也看出来对一些任务来讲,Python取代Java是明显的趋势啊,但这仅仅是对诸如数据分析、深度学习这样的领域):

from pydriller import RepositoryMining
import datetime

repo_dir='%wicket这个Repo的本地目录%'
the_version="ca03c252b5745bdccfb7c8cdffcc705846593ec1"

this_version_time=datetime.datetime.now()
for commit in RepositoryMining(repo_dir, single=the_version).traverse_commits():
    this_version_time=commit.committer_date
    
print(this_version_time.strftime('%b-%d-%Y %H:%M:%S'))

那么得到的结果依然是CommitDate,如果不仔细看,想和Git Log中的Date做匹配的话,就会有bug。

Python的输出如下:

Mar-19-2019 11:53:23

综上所述,这个Bug(其实不能算bug,是大家直觉和默认Git Show、Log中信息不符的问题)肯定会让很多朋友困惑,所以我简单总结一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值