Переместить неуместный коммит в новую ветку - PullRequest
0 голосов
/ 12 сентября 2018

Установка: Я передал изменение кода на локальный, а также на удаленный, но не в ту ветку.

Мое решение:

  1. Выгрузили мастер и создали ветку, где изменение кода должно быть
  2. Вишня выбрала коммит из неправильной регистрации ветки и передала в новую ветку.
  3. Проверьте не ту ветку. Сброс до первого правильного коммита а затем принудительно нажмите его снова, чтобы удалить ошибочный коммит на удаленном филиал.

Вопрос : Это путь? Если я в Google, я получаю, что люди используют revert, и я не могу понять почему, поскольку это кажется более сложным и более опасным. Почему я должен использовать revert?

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Вместо 3 я бы предложил перебазировать на :

git rebase --onto COMMIT_BEFORE_WRONG WRONG_COMMIT branch_with_wrong_commit
git push --force-with-lease

Это "режет" неправильный коммит.

При добавлении -i (для интерактив ) вы можете проверить, что правильные коммиты перемещены.


Тот же результат будет с:

git rebase -i COMMIT_BEFORE_WRONG

и затем изменив слово pick на drop в первой строке представленного файла "todo".

0 голосов
/ 12 сентября 2018

Я [вижу], что люди используют возврат, и я не могу понять почему, поскольку это кажется более сложным и более опасным. Почему я должен использовать возврат?

Должен ли это сильное слово.(Не настолько сильный, как должен или должен , но, по крайней мере, достаточно сильный. :-))

... Сброс до первого правильного коммитаи затем принудительно нажмите его еще раз, чтобы удалить ошибочный коммит в удаленной ветви

Всякий раз, когда вам нужно использовать git push --force или эквивалент, вы перемещаете имя ветви так, как другие люди могли бы не ожидайте.( Может слабее, чем должен: в частичном порядке, я бы сказал может <может <может <должен <должен / должен </em>.) В частности, имена веток Gitестественно двигаться в прогрессии, в которой коммиты добавляются к ветвям, из-за того, как ветки растут при совершении коммитов.

Рассмотрим:

$ git checkout <somebranch>
... work ...
$ git add <files>  # or --all or . or whatever
$ git commit

git checkout step имеет эффект присоединения HEAD к ветви и копирования tip commit этой ветви , на который указывает имя ветви, в индекс и рабочее дерево вашего Git, чтобы вы могли работать с ним:

... <-F  <-G  <-H   <--branch (HEAD)

Ветвь с именем branch - ссылка, полное имя которой refs/heads/<em>branch</em> - хранит необработанный хэш-идентификатор некоторого коммита H.Коммит H сам хранит необработанный хэш-идентификатор своего родительского коммита G, в котором хранится необработанный хэш-идентификатор некоторого коммита F и т. Д.Итак, мы говорим, что имя указывает на подсказку коммита H, которая указывает на более ранний коммит G и т. Д.

Шаг git add обновляет ваш индекс /staging-area, чтобы он был готов к коммиту, а шаг git commit создает новый коммит.Новый коммит хранит в качестве родительского хеш-идентификатора хеш-код текущего извлеченного коммита H.(Разумеется, в качестве снимка хранится замороженный снимок, сделанный из текущей области индекса / промежуточной области.) Затем, в качестве последнего шага, git commit записывает идентификатор хэша нового коммита в имя ветви, к которой прикреплен HEAD:

... <-F  <-G  <-H  <-I   <--branch (HEAD)

Так растут ветви, по одному коммиту за раз, когда люди делают коммиты.Когда вы объединяете серию коммитов в массовом порядке, либо в виде реального слияния, либо в виде ускоренной операции «не реально слить вообще», ветвь также получает новые коммиты, возможно, сразу много, а может инелинейным образом, но важно то, что новые коммиты всегда ведут к существующим коммитам:

...--F--G--H--I---M   <-- master (HEAD)
         \       /
          J--K--L   <-- develop

Добавление коммитов слияния M к master оставляет коммиты H и I достижимо из master, потому что мы можем следовать внутренним стрелкам фиксации в обратном направлении, отображаемым здесь в виде линий, потому что стрелки слишком трудно рисовать в тексте сейчас -используя стрелку верхнего ряда из M.(Стрелка влево и вниз от M до L позволяет нам ездить также с M, скажем, K или J. Думай как (а) Git есть хорошая аналогия с транзитной системой в Портленде, хотя любая столичная железнодорожная система похожа.)

Но предположим, что мы делаем это вместо этого:

...--F--G--H--X  <-- master (HEAD)
         \
          J--K   <-- develop

и затем понимаем, что, к сожалению, мыозначает поместить коммит X в develop.Мы используем любые средства, подходящие для копирования X для нового коммита, такие как cherry-pick или git rebase --onto (оба выполняют одну и ту же работу).Затем мы используем git checkout master; git reset --hard master~1, чтобы оттолкнуть X с пути, чтобы он больше не включался master:

             X
            /
...--F--G--H  <-- master (HEAD)
         \
          J--K--L   <-- develop

(Здесь L - копия X, поместите гдемы хотели этого.) Такого рода движение имен веток оставляет коммит X висящим без какого-либо способа найти его - по крайней мере, никак не в нашем репозитории.Но если мы уже используем git push для отправки коммита X куда-то еще, у некоторого другого Git есть имя для него.Фактически, мы тоже:

             X   <-- origin/master
            /
...--F--G--H  <-- master (HEAD)
         \
          J--K--L   <-- develop

Наш origin/master, который является способом поминания нашего Git master на origin, все еще помнит, что коммит X существует.Это означает, что Git origin помнит X как на их master.

, которыефактически, это , почему мы должны использовать git push --force origin master: чтобы сказать Git в origin, что он должен отбросить свой коммит X. Если мы сделаем это раньше, чем кто-либо еще - любой, у кого есть доступ к этому Git - также копирует X в их репозиторий Git, мы в порядке: никто не видел X, так что никто не может пострадать, если мы удалим X.

Проблемы начинают накапливаться, если кто-то еще сделал захватить копию другого Git. Теперь есть третий репозиторий Git, в котором все еще есть коммит X, возможно, в их master. Возможно, они построили новые коммиты поверх (их копия) X, которые они хотят сохранить:

...--F--G--H--X--Y--Z   <-- master (HEAD)

Теперь мы скажем им: О, забудь X, забери его и из своего хранилища. Это требует, чтобы они сделали свои git rebase --onto или аналогичные, чтобы скопировать их Y и Z для новых коммитов, которые больше не возвращаются к X.

Короче говоря, удаляя X из нашего Git и из origin Git, мы обременяем всех, кто разделяет эти репозитории Git: они тоже все должны удалить свои X и справиться с любыми последствиями.

Существуют проекты, в которых все согласны с тем, что это может произойти - либо в любое время с любой веткой, либо в любое время с некоторым конкретным подмножеством (ами) ветвей. В этих проектах сброс ветвей и принудительное нажатие - это нормально. Есть проекты, в которых нет других пользователей или где вы можете принудительно нажать, прежде чем кто-либо сможет обнаружить ошибку; в этих случаях сброс и принудительное нажатие также хороши. Проблемы возникают, когда вы начинаете много работать для людей, которые не готовы это делать. В этом случае создание нового коммита, который просто un-делает работу в X дает им возможность включить эту новую работу таким образом, что они являются готов принять.

0 голосов
/ 12 сентября 2018

Когда вы revert делаете какой-то коммит, вы создаете коммит, который отменяет целевой коммит. Результат, как с reset, но вам не нужно force push, вы можете сделать простое push, потому что вы добавляете в историю, а не удаляете из нее. Еще одно отличие, которое вы можете revert совершить, это не последнее в истории. Вы не можете использовать reset в этом случае, потому что это приводит к потере всех коммитов, так как целевой коммит.

Также вы можете посмотреть этот вопрос: В чем разница между Git Revert, Checkout и Reset?

...