Jgit: как показать измененные файлы в коммите слияния

Я хотел бы использовать jgit для получения списка файлов, которые были изменены в коммите слияния, аналогично тому, что git show --name-only делает в git.

Существует множество примеров того, как получить измененные файлы для обычных коммитов с одним родителем, но они не работают для коммитов слияния с несколькими родителями.


person Peter Knego    schedule 01.12.2015    source источник


Ответы (1)


Насколько я понимаю, вам просто нужно объединить различия родителей коммита слияния с их соответствующими родителями.

Фрагмент ниже создает два коммита с каждым добавленным файлом (main.txt и side.txt), затем коммит слияния отличается, как описано выше.

public void diffMerge() throws Exception {
  RevCommit baseCommit = commitChanges();
  Ref sideBranch = git.branchCreate().setName( "side" ).call();
  File mainFile = new File( git.getRepository().getWorkTree(), "main.txt" );
  mainFile.createNewFile();
  RevCommit mainCommit = commitChanges();
  git.checkout().setName( sideBranch.getName() ).call();
  File sideFile = new File( git.getRepository().getWorkTree(), "side.txt" );
  sideFile.createNewFile();
  RevCommit sideCommit = commitChanges();
  git.checkout().setName( "refs/heads/master" ).call();
  ObjectId mergeCommitId = git.merge().include( sideCommit ).call().getNewHead();

  DiffFormatter diffFormatter = new DiffFormatter( NullOutputStream.INSTANCE );
  diffFormatter.setRepository( git.getRepository() );
  RevCommit mergeCommit = parseCommit( mergeCommitId );
  List<DiffEntry> mainEntries = diffFormatter.scan( parseCommit( mergeCommit.getParent( 0 ) ).getParent( 0 ), mergeCommit.getParent( 0 ) );
  List<DiffEntry> sideEntries = diffFormatter.scan( parseCommit( mergeCommit.getParent( 1 ) ).getParent( 0 ), mergeCommit.getParent( 1 ) );
  diffFormatter.close();

  mainEntries.forEach( entry -> System.out.println( entry.getNewPath() ) );
  sideEntries.forEach( entry -> System.out.println( entry.getNewPath() ) );
}

private RevCommit parseCommit( ObjectId commitId ) throws IOException {
  try( RevWalk revWalk = new RevWalk( git.getRepository() ) ) {
    return revWalk.parseCommit( commitId );
  }
}

private RevCommit commitChanges() throws GitAPIException {
  git.add().addFilepattern( "." ).call();
  return git.commit().setMessage( "commit message" ).call();
}

Обратите внимание, что код слепо предполагает, что родители коммитов слияния сами по себе не являются слияниями.

person Rüdiger Herrmann    schedule 01.12.2015
comment
Извините, но приведенный выше код просто находит изменения между двумя коммитами (родительским и его родителем) - он делает это для каждой ветки отдельно. Я ищу способ получить только файлы, которые были изменены в фиксации слияния, но не перед этим. Измененные файлы либо нужно было объединить вручную из-за конфликта слияния, либо у пользователя действительно были некоторые изменения в подготовке. git show --name-only находит эти файлы, но в jgit для них нет фарфоровой команды. В приведенном выше случае она git show --name-only ничего не показала бы. - person Peter Knego; 02.12.2015
comment
Разве это не будет комбинированным различием коммита слияния с обоими его родителями? т.е. diffFormatter.scan( merge, merge.getParent( 0 ) )` в сочетании с diffFormatter.scan( merge, merge.getParent( 1 ) )` . - person Rüdiger Herrmann; 02.12.2015
comment
На самом деле это разница между diffs merged ^ 1 - base и merged ^ 2 - base, а также дополнительные поэтапные изменения, которые пользователь мог внести в фиксацию слияния. - person Peter Knego; 02.12.2015
comment
Разница слияния - parent1 в основном дает вам все изменения, которые были сделаны в другой ветке (parent2). - person Peter Knego; 02.12.2015