Вернитесь к предыдущей фиксации, используя git checkout - PullRequest
0 голосов
/ 15 января 2020

Мне нужно откатить мастер до предыдущего состояния, не отменяя сделанные ранее коммиты. Что является лучшим способом создания новых веток master и rollback master. /| merge branch A into master (commit id a.into.m) | | commit (id a2) branch A | | commit (id 3) branch master | | commit (id a1) branch A \| new branch A commit (id a0) | commit 2 master (id m2) | commit 1 master (id m1) Я пытаюсь создать несколько веток этого и сбросить мастер в предыдущее состояние. ветвь new_calculator из commit (id 3) ветвь new_form из commit (id a2) ветвь rollback_master commit (id m1)

Я пробовал это для всех веток git checkout m1 git checkout -b rollback_master git push origin rollback_master

Когда я делаю запрос на извлечение от rollback_master до master я не вижу никаких изменений. Нечего сливать. Я также попробовал на ветке rollback_master git reset --hard m1 ничего не фиксировать.

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Для того, чтобы вернуть ваш мастер обратно к более старому коммиту / ветви, вам требуется git reset.

Если вы хотите сбросить, например, ветку current в older_branch, выполните

  1. Переключение на ветку current: git checkout current (возможно, после клонирования репо или сохранения незафиксированных изменений)
  2. Необязательно Если вы хотите сохранить все коммиты между current и older_branch, создайте новую ветвь в качестве резервной копии: git branch backup
  3. Сбросьте теперь извлеченную ветку current на older_branch: git reset older_branch

Делая так Ваши извлеченные файлы не будут изменены, таким образом, ваше конечное состояние будет состоять в том, что ваша ветвь current была сброшена до older_branch, но ваши извлеченные файлы по-прежнему имеют версии current до сброса. Вы, вероятно, хотите заменить свои извлеченные файлы на файлы из older_branch. Для этого сделайте git reset --hard.

. Кстати: вы можете сбросить практически любое имя, оно не обязательно должно быть именем ветви - вы также можете использовать вместо этого га sh коммита.

Однако становится все сложнее, если вы имеете дело с удаленными репозиториями, и вы уже добавили current на удаленный компьютер - многие удаленные компьютеры не позволяют изменять уже существующую историю из-за потенциальных конфликтов с другими участниками. Однако есть и другой вариант: вы можете позволить git создать коммит, возвращая старые коммиты, поэтому история не будет изменена, но вы все равно получите current, содержащий точное состояние older_branch. Этот возвратный коммит может быть безопасно перенесен в пульты. Проверьте git revert.

1 голос
/ 16 января 2020

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

Вывод журнала, который вы нарисовали:

 /| merge branch A into master (commit id a.into.m)
| | commit (id a2) branch A
| | commit (id 3) branch master
| | commit (id a1) branch A
 \| new branch A commit (id a0)
  | commit 2 master (id m2)
  | commit 1 master (id m1)

отчасти близок к ASCII-арт-графики, которые git log --decorate --oneline --graph dr aws, но не содержат маленьких звездочек, которые используются для маркировки коммитов:

*   4291fbf Merge dotfiles installer
|\  
| * 4f5b84b dotfiles: add --tar option
| * 8a45ff6 dotfiles: refuse to install over special files
| * e750c89 dotfiles: reshuffle work-to-do code
| * 36aa02c dotfiles: s/--install-to/--homedir/
| * 93c597c dotfiles: simplify FileInfo
| * 4771f69 dotfiles: manipulate home dir .foorc etc
|/  
* 6c9a43a add prototype Dot-files

Обратите внимание, что каждый коммит также имеет уникальный идентификатор ha sh (здесь они укоротили) Эти идентификаторы ha sh являются настоящими именами коммитов.

Branch names просто действуют как указатели , указывающие на эти коммиты. Мне нравится рисовать эти вещи в стороны, а не вертикально, для сообщений StackOverflow. Я также люблю давать им заглавные буквы вместо больших уродливых идентификаторов ha sh. Результат:

...--F--G--H   <-- branch1
            \
             I--J   <-- branch2

Идея в том, что каждое имя ветви указывает на один коммит. Сами коммиты также указывают (назад) один шаг, так что J указывает на I, I указывает на H, H указывает на G и т. Д.

Коммиты, которые находятся «на» ветви в Git, - это те, к которым вы можете обратиться, начав с имени ветви, следуя за его стрелкой к его фиксации, а затем работая в обратном направлении от этой фиксации. Поэтому в некотором смысле лучше сказать, что эти коммиты содержатся в ветви, потому что коммиты до H включены или содержатся в обеих ветвях, в то время как коммиты I и J в настоящее время содержат только branch2.

Теперь, что нужно знать об этих коммитах и ​​именах веток:

  • Никаких коммитов не может быть изменилось. Самое большее, вы можете взять существующий коммит и скопировать его в новую улучшенную версию, которая получит новый и другой идентификатор ha sh.

  • Как мы только что сказали Множество коммитов, содержащихся в некоторой ветви, получают, начиная с точки ветвления, а затем переходя от коммита к коммиту, назад, по одному шагу за раз. Сами имена просто содержат коммит ha sh ID любого коммита, который мы говорим, должен быть последний коммит в ветке.

  • Имена ветвей поэтому двигаться . Их обычное продвижение вперед: мы начинаем с некоторого набора коммитов, подобных приведенным выше, а затем добавляем новый коммит. Например, если мы git checkout branch1, мы получим commit H. Если мы сделаем новый коммит, он получит новый идентификатор, который мы назовем K (I и J используются):

    ...--F--G--H---K   <-- branch1 (HEAD)
                \
                 I--J   <-- branch2
    

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

  • Обычное движение, как мы только что видели, это добавление. Давайте слить branch2 в branch1. Не беспокоясь о том, как Git выполняет это, давайте нарисуем результат:

    ...--F--G--H---K--L   <-- branch1 (HEAD)
                \    /
                 I--J   <-- branch2
    

    Новый коммит L - это коммит слияния , то есть один с двумя родителями (или более чем два, но мы не увидим этого здесь).

Возвращаясь к вашему вопросу

Так как имена веток просто указывают на указанные c коммиты, мы можем добавить другие имена и / или заставляют имена двигаться в направлениях, которые они обычно не делают:

 ...--F--G--H---K--L   <-- branch1 (HEAD), master
             \    /
              I--J   <-- branch2

Давайте заставим имя master указывать на фиксацию K вместо L:

$ git branch -f master <hash-of-K>

и нарисуйте результат:

               K     <-- master
              / \_
             /    \
 ...--F--G--H------L   <-- branch1 (HEAD)
             \    /
              I--J   <-- branch2

Ничего не изменилось изменилось с точки зрения фиксации, но метки сместились.

Но master двигался в «неправильном» направлении. Если мы соединяем наши Git с некоторыми другими Git и их master точками для фиксации L, и мы просим их переместить своего мастера в точку для фиксации K, как наша они обычно говорят нет . Причина, по которой они скажут «нет», заключается в том, что это движение метки ветки идет в неправильном направлении. Термин Git означает, что это не ускоренная перемотка вперед .

Мы можем использовать команду git push --force to , чтобы переместить их master нравится. Они могут или не могут подчиняться. Другие клоны нашего или их репозитория могут также иметь master, который указывает «впереди» коммит K, например, L, и нам придется убедить их переместить то же самое way.

Итак:

Я пытаюсь создать несколько ветвей этого и сбросить мастер в предыдущее состояние. ветвь new_calculator из commit (id 3) ветвь new_form из commit (id a2) ветвь rollback_master commit (id m1)

Вы можете сделать это в своем собственном Git хранилище где вы все контролируете. Просто поменяйте ярлыки и делайте новые ярлыки по мере необходимости. Все существующие коммиты остаются на месте; двигаются только метки . См. Ответ Михаэля Бера для получения более подробной информации о том, как это сделать (с git reset и / или git branch -f).

Вы не обязательно сможете изменить кого-либо репозиторий Git. Сюда входит любая копия вашего собственного Git репозитория, которую вы поместили на GitHub. В конце концов, это репозиторий GitHub, а не ваш: они просто позволяют вам контролировать его, и они сами решают, какой контроль вам предоставить.

Если вы владеете им, чтобы GitHub предоставил вам полный контроль, и никто больше не имеет Git репозиториев, о которых вам нужно беспокоиться, вы можете git push --force обновлять свой репозиторий GitHub (он же «репозиторий GitHub, который они хранят для вас»).

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

Когда я делаю вытащить запрос rollback_master в master ...

Запросы на извлечение не являются частью Git. Это расширение, предлагаемое такими сервисами, как GitHub.

Когда вы делаете запрос на извлечение, вы прикрепляете метку - фактическая метка зависит от сервиса - к некоторому коммиту в каком-то хранилище, которое существует на сервере. Этот коммит имеет некоторый идентификатор ha sh, как и все коммиты. Затем сервер доставляет запрос на удаление (в комплекте с внутренней прикрепленной меткой) тому, кому он управляет другим хранилищем - тем, с которого вы ответили. (Сервер где-то записал этот репозиторий. В некоторых случаях вы выбираете этот «другой» репозиторий, этот репозиторий; тогда кто-то является владельцем этого репозитория.) Этот человек получает пользовательский интерфейс, который позволяет ему:

  • запустите слегка измененный git merge на сервере GitHub, или
  • запустите слегка измененный git rebase на сервере GitHub, или
  • запустите слегка измененный git merge --squash на сервере GitHub.

Ни один из этих шагов не включает git push --force операцию «произвольно переместить метку». Все они либо вообще, либо специально создают новый коммит, который добавляет к существующим коммитам. Таким образом, все операции, выполняемые с помощью запросов на получение, обязательно очень отличаются от вида git push --force, который перемещает метку назад.

Иными словами, если вы go идете по этому пути, «вы не можете получить там отсюда ". : -)

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