Как я могу сделать unpushable коммитов pushable? - PullRequest
2 голосов
/ 23 февраля 2012

Master Ветка имела такие коммиты: A -> B -> C(HEAD). HEAD было на C.

Что я сделал:

Я проверил B и сделал коммиты поверх него.

Теперь дерево выглядит так:

    A -> B -> C(master)(origin/master)
         |
         | -> B1 -> B2(HEAD)

git status в каталоге проекта выдает мне следующее сообщение:

# Not currently on any branch.
nothing to commit (working directory clean)`

Таким образом, это означает, что B1 и B2 нельзя нажать. Я узнал, что это происходит, потому что эти коммиты не существуют ни в одной ветви. Теперь, если я переключу свою ветку обратно на master, эти коммиты будут потеряны? Я ожидаю еще несколько коммитов (B3, B4 ... BN) в этой безымянной ветви, после чего я хочу, чтобы C встал поверх нее. По сути, я бы хотел увидеть ветку master следующим образом:

    A -> B -> B1 -> B2 -> B3 -------> BN -> C(master)(origin/master)

или, по крайней мере, так:

    A -> B ---------------------> C(master)(origin/master) -> D
         |                                                    ^
         |                                                    |
         | -> B1 -> B2 -> -> ...->BN--------------------------

Какие варианты у меня есть для этого? Я хочу сохранить коммиты в origin.

Любые предложения / указания приветствуются.

Ответы [ 4 ]

3 голосов
/ 23 февраля 2012

Ваш желаемый результат

A -> B -> B1 -> B2 -> B3 -------> BN -> C(master)(origin/master)

невозможно, если вы не можете переписать C в удаленном репо; это может вызвать проблемы у всех, кто выполнил работу на основе C .

Второе предпочтение

A -> B ---------------------> C(master)(origin/master) -> D
     |                                                    ^
     |                                                    |
     | -> B1 -> B2 -> -> ...->BN--------------------------

легко: как говорит Магнус, вы сделаете свою жизнь намного проще, если дадите B2 (или каков текущий последний коммит в вашей последовательности) имя ветви: это легче запомнить и введите, чем хэш, и убедитесь, что он не собирает мусор.

git checkout -b bbranch

A -> B -> C(master)(origin/master)
     |                                                    
     |                                                    
     | -> B1 -> B2 (bbranch)

Теперь, если по какой-либо причине вы хотите подтолкнуть B1 и B2 к источнику, вы можете объединить и нажать как обычно

git checkout master
git pull
git merge bbranch

A -> B ------> C -> D (master)
     |             /
     |            /
     | -> B1 -> B2 (bbranch)

git push

Вы можете продолжать работать на bbranch и объединить снова , когда вы закончите с этим

A -> B ------> C -> D -> E -> ... -> En -> F (master)
     |             /                      /
     |            /                      /
     | -> B1 -> B2 -> B3  ->  ...  -> Bn  (bbranch)

Примечание: если по какой-либо причине вы хотите отправить свои коммиты на origin , но вы не хотите, чтобы они были на master , вы можете просто нажать bbranch и он возьмет с собой ваши коммиты. Затем вам нужно будет либо быть уверенным, что никто не коснется bbranch , либо сделать вашу локальную копию веткой удаленного отслеживания.

Заменить шаг объединения B2 -> D на git push origin bbranch в этом случае.

1 голос
/ 23 февраля 2012

То, что вы просите, если я вас правильно понимаю, это способ сделать коммиты видимыми во внешнем репозитории , когда они не являются частью ветви .

Коммиты B1 и B2 доступны по их хешу SHA1, но не по любому именованному ref. Таким образом, с точки зрения git, они являются «мусором» и в конечном итоге будут очищены на git gc (по истечении достаточного периода времени, определенного вашими настройками).

Когда вы делаете git push, он проталкивает изменения, которые являются «частью» вашего хранилища. Это включает в себя все наборы изменений , доступные из именованного ref . «Мусорные» коммиты не уходят.

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

Если, с другой стороны, вы готовы сделать свободные коммиты частью master ветви, вам нужно git rebase (поместить их поверх текущего master) или git merge (чтобы интегрировать их с мастером при сохранении точной истории, которая у вас есть). Вы также можете переписать ветку master, чтобы включить коммиты в качестве «первого» примера, но я не рекомендую этого (особенно если вы уже нажали master в другом состоянии).

Чтобы более четко ответить на ваш вопрос «если я переключу свой HEAD обратно на master, эти коммиты будут потеряны?», Ответ «в конечном итоге, да, но сразу, нет». Вы можете проверить явные идентификаторы SHA1 коммитов (и найти те, которые используют git reflog или синтаксис HEAD@{1}). Но со временем они уйдут, если вы не прикрепите к ним именованный реф.

1 голос
/ 23 февраля 2012

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

git checkout B
git checkout -b fix
.. do some stuff
git commit -am 'did some stuff to B'
git checkout master
git merge fix

Первый ответ:

git checkout master
git merge B2

Ваши коммиты никогда не будут потеряны, если вы не очистите ссылки на них (с помощью git gc и т. Д.). Пока вы зафиксировали свои изменения, вы в безопасности.

0 голосов
/ 23 февраля 2012

Проверьте git rebase с опцией --interactive.

...