Как перезапустить слияние для конфликта «pull --rebase» - PullRequest
0 голосов
/ 03 октября 2019

Я работаю над плагином Git, основанным на JGit из Eclipse Foundation, и у меня уже было реализовано " Restart merge " коллегой на случай возникновения конфликтов при попытке выполнить извлечение по умолчанию (с объединением).

Теперь я работаю над действием " Pull (rebase) ". Когда возникают конфликты, и пользователь вносит некоторые изменения в конфликтующий файл, я бы хотел, чтобы они могли перезапустить слияние. Я заметил, что у некоторых клиентов Git нет этой опции (EGit для Eclipse, GitKraken Free), а у некоторых она есть (SourceTree).

Мой текущий код выглядит так:

public void restartMerge() {
    try {
      RepositoryState repositoryState = getRepository().getRepositoryState();
      String revision = repositoryState == RepositoryState.REBASING_MERGE ? "HEAD" : "MERGE_HEAD";
      AnyObjectId commitToMerge = getRepository().resolve(revision);
      git.clean().call();
      git.reset().setMode(ResetType.HARD).call();

      if (repositoryState == RepositoryState.REBASING_MERGE) {
        // TODO: regenerate the conflict
      } else {
        git.merge().include(commitToMerge).setStrategy(MergeStrategy.RECURSIVE).call();
      }

      fireFileStateChanged(new ChangeEvent(GitCommand.MERGE_RESTART, Collections.<String> emptyList()));
    } catch (IOException | NoRepositorySelected | GitAPIException e) {
        if (logger.isDebugEnabled()) {
            logger.debug(e, e);
        }
    }
}

Я думаю, что мне нужно снова сделать ребаз или что-то в этом роде, чтобы заново создать конфликт, как мой коллега сделал новый merge(). Но в этот момент я нахожусь на отдельном ГОЛОВЕ ... Я попытался перейти на ветку master и снова перебазировать, имея origin/master в качестве восходящего потока, но это не сработало ...

Что быкоманды Git для перезапуска конфликта перебазирования? Возможно, я смогу выполнить их, используя JGit ...

Ответы [ 2 ]

1 голос
/ 03 октября 2019

Как вы видели, git pull - это в основном:

  • run git fetch
  • , затем выполните вторую команду Git, обычно, но не всегда git merge

Объединение может прекратиться с конфликтами. Вы можете разрешить пользователю исправлять конфликты и возобновлять их, или прервать объединение и вернуть все обратно к тому, что было до начала объединения:

  • Чтобы разрешить пользователю возобновить работу после устранения конфликтов вручную, вы просто вызываете либо git merge --continue, либо git commit: git merge --continue сам проверяет, что происходит слияние, в котором исправлены конфликты, а затем вызывает git commit.
  • , чтобы прервать и поместитьвещи возвращаются такими, какими они были после извлечения, но перед слиянием вы можете использовать git merge --abort или git reset --merge (они делают то же самое).

Вторая команда, однако, может быть git rebase, что также может прекратиться конфликтами. Это может быть даже git read-tree, в некоторых угловых случаях. Поскольку у вас так мало контроля при использовании git pull, я бы порекомендовал никогда использовать его программно: если вы пишете код, выполняющий команды Git, всегда разбивает вашу работу наgit fetch и вашей собственной программно выбранной второй командой Git, чтобы вы знали, какую вторую команду вы выполняете.

Однако проблема с rebase заключается в том, что она по существу состоит из серии git cherry-pickоперации. (В зависимости от того, как вы вызываете git rebase, это может быть git apply --3way, а не git cherry-pick, или он может буквально запускать git cherry-pick.) Каждая операция выбора вишни может быть остановлена ​​конфликтом слияния,Таким образом, у вас не один конфликт, а M конфликтов, M ≤ N , где N - количество коммитов, скопированных в их новую позициюthe rebase.

Чтобы возобновить перезагрузку после того, как пользователь исправит конфликты, вызовите git rebase --continue. Это проверяет, что происходит постоянное обновление, и что конфликты устранены, и фиксирует их и переходит к следующей операции выбора вишни. Перебазирование продолжается до тех пор, пока оно не достигнет другого конфликта слияния или не завершит все вишневые пики;после завершения последнего выбора вишни, перебазирование переназначает значение имени ветви для последнего скопированного коммита и повторно присоединяет HEAD к имени ветви.

Если вы используете git rebase --abort, вы говорите Gitчтобы остановить операции по сбору вишни (включая все те, которые еще не начались) и вернуться в состояние, в котором вы находились до того, как любой из них начался. Если вы разрешаете пользователям разрешать конфликты слияния, обратите внимание, что при этом отбрасываются все разрешенные до сих пор вишневые пики, включая всю работу, которую пользователь выполнял для разрешения конфликтов. Если пользователь включил git rerere, результаты разрешенных слияний записываются в кэш повторного использования, так что это не всегда слишком страшно.

Нет отличных решений для конфликтов слияния. Если бы был способ надежно автоматизировать это, Git уже сделал бы это.

1 голос
/ 03 октября 2019

Вы можете попробовать запустить git rebase --abort и перезапустить ваш ребаз, используя git pull --rebase в вашем случае.

...