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

Я хочу нажать несколько отдельных коммитов на удаленное репо git. Я последовал за ответом Джеффа, который нашел здесь:

Как я могу нажимать конкретную фиксацию на удаленный, а не на предыдущие коммиты?

Записи, которые я хочу нажать, не находятся во главе, поэтому я должен переупорядочить коммиты, используя сначала rebase, и я использовал эти инструкции для этого:

http://gitready.com/advanced/2009/03/20/reorder-commits-with-rebase.html

По существу, я сделал:

git clone
git commit
git commit
...
git pull
git rebase -i HEAD~3
git push origin <SHA>:master

У меня возникли ошибки. Поэтому я начал глубже вникать в проблему. Я обнаружил, что в моем журнале есть повторяющиеся коммиты, если я делаю второй git pull после перезагрузки, например:

git clone
git commit
git commit
...
git pull
git log --pretty=format:"%h - %an : %s" // log before rebasing
git rebase -i HEAD~3
git pull
git log --pretty=format:"%h - %an : %s" // log after rebasing
git pull 
git log --pretty=format:"%h - %an : %s" // log after rebasing after pulling

Итак, я разместил этот вопрос:

git: повторяющиеся записи после локальной пересылки, следующие за помощью Pull

Ответ Роджера привел меня к этому вопросу: почему я вижу повторяющиеся фиксации после перезагрузки и вытягивания?

Сверху журнал перед перезагрузкой выглядит следующим образом:

84e4015 - Me : Local Commit 3
0dbe86a - Me : Local Commit 2
d57ba2a - Me : Merge branch 'master' of remote repository
a86ea35 - Me : Local Commit 1 before reordering
2fc4fe7 - Remote User 2 : Remote Commit 2
b7a8656 - Remote User 1 : Remote Commit 1
8ce80fc - Me : Merge branch 'master' of remote repository

И журнал после перезагрузки выглядит следующим образом:

cf1ff7b - Me : Local Commit 3
cd14463 - Me : Local Commit 2
b9d44fb - Me : Local Commit 1 after reordering
9777c56 - Remote User 2 : Remote Commit 2
a2d7d8b - Remote User 1 : Remote Commit 1
8ce80fc - Me : Merge branch 'master' of remote repository

Обратите внимание, что оригинал 2 совершает 2fc4fe7 и b7a8656 имеет новые SHA; 9777c56 и a2d7d8b. Я считаю, что это начало проблемы.

Теперь после того, как я сделаю еще один git pull, журнал выглядит следующим образом:

e8e1a85 - Me : Merge branch 'master' of remote repository
cf1ff7b - Me : Local Commit 3
cd14463 - Me : Local Commit 2
b9d44fb - Me : Local Commit 1 after reordering
9777c56 - Remote User 2 : Remote Commit 2
a2d7d8b - Remote User 1 : Remote Commit 1
2fc4fe7 - Remote User 2 : Remote Commit 2 // duplicate 2
b7a8656 - Remote User 1 : Remote Commit 1 // duplicate 1
8ce80fc - Me : Merge branch 'master' of remote repository

Обратите внимание, что удаленные коммиты теперь дублируются, и исходные SHA удаленных коммитов, 2fc4fe7 и b7a8656, вернулись.

В ответ Роджера он сказал, что это похоже на ошибку других людей, подталкивающих к git, и что они перегружают свои и без того толкаемые коммиты. Но я считаю, что это моя ошибка для локального переустановки нажатой фиксации.

Это потому, что я переустановил фиксацию, которая уже была нажата на пульт? Если да, то что я должен был сделать, чтобы избежать этого? Мне нужно переустановить мои коммиты, чтобы я мог нажимать одну фиксацию. Должен ли я использовать систему ветвления для этого? Если да, как использовать ветки для решения этой проблемы?

Ответ 1

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

Как правило, вы должны только переустанавливать свои личные, неопубликованные коммиты. Поскольку у кого-то нет такой копии по определению, тот факт, что вы делаете свои собственные копии, а затем (через rebase) скрываете свои оригиналы, не проблема: теперь вы видите свои копии вместо своих оригиналов, и никто больше не видит либо, и вы можете продолжить переустановку, если это необходимо. Как только вы опубликуете (через push или подобное) коммит, вы больше не сможете его изменить, потому что у кого-то теперь есть копия вашего оригинала, включая его идентификатор SHA-1, и они все равно будут иметь его позже.

То, что вы сделали в этом случае, - это переустановить (то есть скопировать) свои коммиты, а также ваши собственные. Часть проблемы связана с использованием git pull, что означает "выборка, затем слияние", когда вам нужно было "выборка, а затем перебаза". Вы можете выполнить эти шаги отдельно:

git fetch
git rebase

или используйте git pull --rebase:

git pull --rebase

который сообщает pull script, что после выполнения выборки вместо слияния он должен использовать rebase. Вы также можете настроить Git для этого автоматически, без аргумента --rebase. 2

Основная проблема прямо сейчас в том, что у вас есть слияние, которого вы, вероятно, не хотели. Если это так, вам нужно "отменить" это слияние (с помощью git reset, см. Другие публикации в стеке).


1 Он не может: объект Git, включая commit, именоваться его идентификатором объекта, который является контрольной суммой для его содержимого. Конец состоит из его родительского идентификатора, идентификатора дерева, автора фиксации и коммиттера (имя, адрес электронной почты и метки времени) и сообщения фиксации. Если вы измените какой-либо из них, вы получите новую, другую фиксацию с другим идентификатором.

2 Вы даже можете настроить его на использование git pull --rebase=preserve. Тем не менее, сохранение объединений в операциях переадресации - это отдельный раздел (который я уже рассмотрел ранее в проводниках stackoverflow).