git-svn делает один коммит git - PullRequest
26 голосов
/ 10 августа 2009

При наличии нескольких не нажатых git коммитов, возможно ли git-svn dcommit только один из этих коммитов?

например. У меня есть коммит foo, bar и baz, но сейчас я хочу, чтобы bar попал в репозиторий SVN. Возможно ли это?

Ответы [ 4 ]

27 голосов
/ 30 ноября 2011

(ниже предполагается, что ваша работа включена master.)

Во-первых, измените порядок последних трех коммитов, чтобы bar был первым.

git rebase -i HEAD~3

В редакторе появится что-то вроде этого:

pick 498e4f4 foo
pick 71547ae bar
pick abf09c6 baz

# Rebase 4d3fe72..abf09c6 onto 4d3fe72
#
# ...

Переупорядочьте их в всплывающем редакторе, чтобы bar был первым.

pick 71547ae bar
pick 498e4f4 foo
pick abf09c6 baz

# Rebase 4d3fe72..abf09c6 onto 4d3fe72
#
# ...

Git будет вращаться в течение нескольких секунд и выдавит подтверждение:

Successfully rebased and updated refs/heads/master.

Теперь вы можете временно откатиться до коммита bar (HEAD~2 означает два коммита от HEAD) и отменить его:

git checkout HEAD~2
git svn dcommit

Если вы параноик, как я, вы можете сначала сделать git svn dcommit -n, чтобы убедиться, что вы делаете только то, что хотите.

Теперь вернитесь к master:

git checkout master

Последний бит должен быть перебазирован так, чтобы master синхронизировался с svn:

git svn rebase

Мне немного неясно, почему это требуется, но я предполагаю, что dcommitting в отключенном состоянии HEAD как-то связано с этим.

13 голосов
/ 12 августа 2009

git svn dcommit не может выборочно зафиксировать бар. если вы непосредственно зафиксировали foo, bar и baz в своей основной ветке, то вам нужно сделать следующее, чтобы получить только bar в svn.

Предположим, что commit шага бара - что-то вроде 13abc ...

и git log master показывает все ваши 3 коммитов foo, bar и baz.

  • вам нужно создать ветку от мастера

    git branch wip

В ветке wip теперь есть foo, bar и baz

  • сбросить голову мастера на коммит перед любым из foo, bar или baz. это можно сделать с помощью git reset (прочитайте руководство, различия между жесткими, программными и смешанными параметрами влияют на незавершенные изменения в рабочем дереве)

    git reset --hard (COMMIT-ID перед foo, bar, baz)

    (или)

    git reset --hard HEAD ~ 3 (вернуться на 3 ревизии)

теперь в вашей основной ветке нет ни foo, ни bar, ни baz. сверьтесь с git log.

  • теперь вы можете выбрать только те коммиты, которые вы хотите записать в svn из ветки wip в master. так, чтобы получить бар

    гирь с вишневым салом 13abc (ша бар)

мастер получает только коммит в баре.

  • теперь git svn dcommit должен нажимать один бар.

Рекомендуемое будущее использование

Так что для git-svn предпочтительно не делать коммиты непосредственно в ветке master, которая отслеживает удаленный svn. выполняйте свою работу в локальных филиалах и выборочно объединяйтесь с мастером, прежде чем завершить работу.

4 голосов
/ 10 августа 2009

У меня есть один вид хрустящего ответа. Вы можете создать новую ветку без foo, bar и baz, а затем cherry-pick bar до новой ветви и затем git-svn dcommit этой ветви и удалить ее, когда закончите. Это выглядит не очень элегантно.

Предполагается, что foo, bar и baz находятся в ветви x, а master не имеет ни одного из них.

git branch y master

git checkout y

git cherry-pick <sha1 of bar>

git svn dcommit

git checkout x

git svn rebase

git branch -d y

Если мастер имеет эти коммиты, вы можете сбросить голову, как советует Сиззлер.

2 голосов
/ 13 октября 2015

Иногда я хочу совершить всего несколько коммитов моей ветки. Э.Г.

A-----B-----C------D  
^                  ^
|                  |
svn/trunk          trunk

Если я хочу зафиксировать B и C, но не D, я создаю новую ветку, делаю svn dcommit, переключаюсь обратно на trunk и удаляю ветку.

Пока я на ветке trunk Я делаю

git checkout -b temp `C`
git svn info // just to check that branch temp is properly connected to svn
git svn dcommit
git checkout trunk
git branch -D temp

EDIT

Как прокомментировал Стефан:

С дополнительным 'git svn rebase' это хорошо сработало.

Это необходимо, потому что коммиты, которые фиксируются в SVN, будут переписаны. git-svn добавляет git-svn-id к сообщению фиксации, и, следовательно, хэш-фиксация изменяется, даже если содержимое фиксации одинаково. Но поскольку содержимое одинаковое, перебазирование не вызовет конфликтов.

PS: Я также часто опускаю новую ветку и просто извлекаю извлечение . Э.Г.

git checkout --detach C
git svn dcommit
git checkout trunk
git svn rebase 
...