Требуется ли git svn rebase до git svn dcommit?

Я читаю об использовании git в качестве svn-клиента здесь:

http://learn.github.com/p/git-svn.html

Эта страница предполагает, что вы выполняете git svn rebase до git svn dcommit, что имеет смысл; ему нравится делать обновление svn перед выполнением svn commit. Затем я начал смотреть документацию на git svn dcommit (мне было интересно, что такое "d" ):

http://git-scm.com/docs/git-svn

Вам нужно немного прокрутить список документов dcommit, который говорит следующее:

Перенесите каждый diff из указанной главы непосредственно в репозиторий SVN, а затем rebase или reset (в зависимости от того, существует или нет различие между SVN и головкой).

Это меня смущает, потому что если вы сделаете, как говорит первая страница, не будет никаких изменений, чтобы свернуть с svn после завершения первой части dcommit.

Меня тоже смущает часть, которая говорит о reset; не git reset для удаления изменений из промежуточной области?

Почему бы rebase или reset следовать (первая часть) dcommit?

Ответы

Ответ 1

Отказ от ответственности: Обычно я обычно запускаю git svn rebase перед тем, как сделать git svn dcommit. Обычно я сохраняю свои изменения в другой ветке git, так что rebase не имеет никаких шансов на неудачу. Я использую git rebase master в моей ветке темы, чтобы обновить ее. Затем я переключаюсь на ветвь master и использую git merge, чтобы включить изменения из моей ветки темы в master (это ускоренная перемотка вперед из-за переадресации).

Мое объяснение ниже объясняет, почему это не является механически необходимым, но я согласен с тем, что это хорошая идея. Ваши изменения могут не вызывать конфликтов с точки зрения различий и слияния, но если вы dcommit ваш код, не получая последние изменения от svn и не просматривая их эффекты, вы можете сделать код svn, который не делает правильные вещи.


Вам не нужно git svn rebase перед запуском git svn dcommit. Если изменения, которые вы хотите выполнить dcommit, находятся в файлах, которые не изменились в svn с тех пор, как вы в последний раз набрали изменения, тогда git -svn не будет отображать конфликт. Таким образом, вы можете совершать изменения в репозитории svn, используя репозиторий git, который не имеет всех последних изменений из svn.

Скажем, я запустил репозиторий svn, содержащий два файла, foo.txt и bar.txt. До сих пор у них только одна ревизия. Я делаю git svn clone, чтобы начать отслеживание репозитория svn с помощью git.

$ git log --oneline --decorate
7e72290 (git-svn, master) Initial commit.

Вы вносите изменения в foo.txt и git commit их в локальную ветвь master, поэтому она перемещается впереди git-svn.

$ git log --oneline --decorate
aa70eca (master) Added a line to foo.
7e72290 (git-svn) Initial commit.

Что вы не понимали, так это то, что ваш друг уже совершил изменения в bar.txt как svn revision 2.

Теперь, когда вы запустите git svn dcommit из master, git будет искать набор изменений между вами и где git-svn. В этом случае у вас есть только один: aa70eca. git пытается отправить этот diff в ваш репозиторий svn.

$ git svn dcommit
Committing to [svn repo address] ...
        M       foo.txt
Committed r3
        M       bar.txt
r2 = 12b95b96e11f782f31b07a78756660cb82437ca2 (refs/remotes/git-svn)
        M       foo.txt
r3 = d4a7b84e0383f3af5fb0db439169c9f1b8af1152 (refs/remotes/git-svn)
W: aa70ecae4121854ac3754fb882a483b67d706a4a and refs/remotes/git-svn differ, using rebase:
:100644 100644 5771152459bfaa7cc62caa3b6b4d24e52ab8e447 dbfaecb10330d0509e092f1891a4a7e673802413 M      bar.txt
First, rewinding head to replay your work on top of it...
Nothing to do.

$ git log --oneline --decorate
d4a7b84 (git-svn, master) Added a line to foo.
12b95b9 Added to bar.
7e72290 Initial commit.

Вы можете видеть, что фиксация выполнена как версия svn 3. Когда git -svn затем синхронизировал вашу локальную историю svn с репозиторием svn, он извлек все новые коммиты, включая изменение, которое вы только что передали в svn. Вы заметите, что это изменение (d4a7b84) имеет другой SHA-хэш из того, который вы использовали для git (aa70eca). Это происходит из-за множества вещей: разные метки времени фиксации, потенциально разные имена авторов, git-svn-id в журнале фиксации, полученной из svn, и разных предков — выбранный svn r3 имеет r2 в качестве родителя, но ваш фиксатор git произошел от r1.

В этом случае обнаружена разница, найденная после выборки между текущей головой git (master) и SVN, поскольку содержимое в r2 изменилось foo.txt. В результате git-svn будет rebase.

Если я сделаю изменение, и между тем никаких других транзакций svn не произошло (или я выполнял git svn rebase для обновления), тогда git-svn не найдет разницу между головкой и SVN, поэтому он может просто reset:

$ git svn dcommit
Committing to [svn repo address] ...
        M       foo.txt
Committed r4
        M       foo.txt
r4 = 533f7337999778628cf39fcd9155d085eb1c2b89 (refs/remotes/git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn