Jgit源码阅览——文件差异比较就是比较index文件的差别
Jgit源码阅读——文件差异比较就是比较index文件的差别
git比较文件差异是根据当前的index文件进行差量比较的.
这些差量信息如:
added files 已经add进index的file,也就是在objects目录中存在备份的file
changed files 内容发生改变,而且在index和版本库中都存在记录的file
removed files 已经被移除的file
missing files 已经不存在的file
modified files 内容发生改变,而且受控目录和index都存在的file
conflicting files 与已经存在版本相冲突的file
untracked files 还没被add进index的file
files with assume-unchanged flag 这个,知道说一下
这个是IndexDiff类中比较当前workTree跟版本库中文件状态 最关键的部分
代码分析:
52行: 过滤器,以当前受控workTree为过滤点
55行:遍历受控目录中所有的文件.
66行:如果版本库中包含该entry,但dirCacheEntry.getStage()大于零, 被记录到版本库后,stage有四个值,如下
这个时候,在受控目录中的文件为冲突态.
78行:如果已经存在index和版本库中,这个文件内容又发生了改变,这个时候,这个文件是changes状态
82-84行:在版本库中,但是已经不在index状态了,是remove状态,
102行,:如果该文件在index中,但是在受控目录不见了,定义为missing状态,一般在eclipse的egit中可以看到这个状态
不一一分析,从此可以看到git在切换分支的时候如此之快,其实就是拿index出来比较,因为index已经索引了文件在objects的位置.
作者:http://414149609.iteye.com/admin/blogs/1668995
git比较文件差异是根据当前的index文件进行差量比较的.
这些差量信息如:
added files 已经add进index的file,也就是在objects目录中存在备份的file
changed files 内容发生改变,而且在index和版本库中都存在记录的file
removed files 已经被移除的file
missing files 已经不存在的file
modified files 内容发生改变,而且受控目录和index都存在的file
conflicting files 与已经存在版本相冲突的file
untracked files 还没被add进index的file
files with assume-unchanged flag 这个,知道说一下
这个是IndexDiff类中比较当前workTree跟版本库中文件状态 最关键的部分
/** * Run the diff operation. Until this is called, all lists will be empty. * <p> * The operation may be aborted by the progress monitor. In that event it * will report what was found before the cancel operation was detected. * Callers should ignore the result if monitor.isCancelled() is true. If a * progress monitor is not needed, callers should use {@link #diff()} * instead. Progress reporting is crude and approximate and only intended * for informing the user. * * @param monitor * for reporting progress, may be null * @param estWorkTreeSize * number or estimated files in the working tree * @param estIndexSize * number of estimated entries in the cache * @param title * * @return if anything is different between index, tree, and workdir * @throws IOException */ public boolean diff(final ProgressMonitor monitor, int estWorkTreeSize, int estIndexSize, final String title) throws IOException { dirCache = repository.readDirCache(); TreeWalk treeWalk = new TreeWalk(repository); treeWalk.setRecursive(true); // add the trees (tree, dirchache, workdir) if (tree != null) treeWalk.addTree(tree); else treeWalk.addTree(new EmptyTreeIterator()); treeWalk.addTree(new DirCacheIterator(dirCache)); treeWalk.addTree(initialWorkingTreeIterator); Collection<TreeFilter> filters = new ArrayList<TreeFilter>(4); if (monitor != null) { // Get the maximum size of the work tree and index // and add some (quite arbitrary) if (estIndexSize == 0) estIndexSize = dirCache.getEntryCount(); int total = Math.max(estIndexSize * 10 / 9, estWorkTreeSize * 10 / 9); monitor.beginTask(title, total); filters.add(new ProgressReportingFilter(monitor, total)); } if (filter != null) filters.add(filter); filters.add(new SkipWorkTreeFilter(INDEX)); indexDiffFilter = new IndexDiffFilter(INDEX, WORKDIR); filters.add(indexDiffFilter); treeWalk.setFilter(AndTreeFilter.create(filters)); while (treeWalk.next()) { AbstractTreeIterator treeIterator = treeWalk.getTree(TREE, AbstractTreeIterator.class); DirCacheIterator dirCacheIterator = treeWalk.getTree(INDEX, DirCacheIterator.class); WorkingTreeIterator workingTreeIterator = treeWalk.getTree(WORKDIR, WorkingTreeIterator.class); if (dirCacheIterator != null) { final DirCacheEntry dirCacheEntry = dirCacheIterator .getDirCacheEntry(); if (dirCacheEntry != null && dirCacheEntry.getStage() > 0) { conflicts.add(treeWalk.getPathString()); continue; } } if (treeIterator != null) { if (dirCacheIterator != null) { if (!treeIterator.idEqual(dirCacheIterator) || treeIterator.getEntryRawMode() != dirCacheIterator.getEntryRawMode()) { // in repo, in index, content diff => changed changed.add(treeWalk.getPathString()); } } else { // in repo, not in index => removed removed.add(treeWalk.getPathString()); if (workingTreeIterator != null) untracked.add(treeWalk.getPathString()); } } else { if (dirCacheIterator != null) { // not in repo, in index => added added.add(treeWalk.getPathString()); } else { // not in repo, not in index => untracked if (workingTreeIterator != null && !workingTreeIterator.isEntryIgnored()) { untracked.add(treeWalk.getPathString()); } } } if (dirCacheIterator != null) { if (workingTreeIterator == null) { // in index, not in workdir => missing missing.add(treeWalk.getPathString()); } else { if (workingTreeIterator.isModified( dirCacheIterator.getDirCacheEntry(), true)) { // in index, in workdir, content differs => modified modified.add(treeWalk.getPathString()); } } } } // consume the remaining work if (monitor != null) monitor.endTask(); ignored = indexDiffFilter.getIgnoredPaths(); if (added.isEmpty() && changed.isEmpty() && removed.isEmpty() && missing.isEmpty() && modified.isEmpty() && untracked.isEmpty()) return false; else return true; }
代码分析:
52行: 过滤器,以当前受控workTree为过滤点
55行:遍历受控目录中所有的文件.
66行:如果版本库中包含该entry,但dirCacheEntry.getStage()大于零, 被记录到版本库后,stage有四个值,如下
/** The standard (fully merged) stage for an entry. */ public static final int STAGE_0 = 0; /** The base tree revision for an entry. */ public static final int STAGE_1 = 1; /** The first tree revision (usually called "ours"). */ public static final int STAGE_2 = 2; /** The second tree revision (usually called "theirs"). */ public static final int STAGE_3 = 3;.
这个时候,在受控目录中的文件为冲突态.
78行:如果已经存在index和版本库中,这个文件内容又发生了改变,这个时候,这个文件是changes状态
82-84行:在版本库中,但是已经不在index状态了,是remove状态,
102行,:如果该文件在index中,但是在受控目录不见了,定义为missing状态,一般在eclipse的egit中可以看到这个状态
不一一分析,从此可以看到git在切换分支的时候如此之快,其实就是拿index出来比较,因为index已经索引了文件在objects的位置.
作者:http://414149609.iteye.com/admin/blogs/1668995