Ответ 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