Потрібно скинути гілку git до початкової версії


439

Я випадково працював на гілці, яку я не повинен був деякий час, тому я розгалужувався, даючи їй відповідну назву. Тепер я хочу перезаписати гілку, в якій я не мав би бути до версії від походження (github). Чи є простий спосіб це зробити? Я спробував видалити гілку, а потім скинути гілку відстеження, але це просто дає мені версію, над якою я працював знову.



З Git 2.23 (серпень 2019): git switch -C mybranch origin/mybranch. Дивіться мою відредаговану відповідь нижче
VonC

Відповіді:


814

Якщо ви ще не натиснули на початкове місце, ви можете скинути свою гілку до верхньої гілки за допомогою:

git checkout mybranch
git reset --hard origin/mybranch

(Переконайтеся, що ви посилаєтеся на останню комісію в окрему гілку, як ви згадуєте у своєму запитанні)

Зауважте, що відразу після скидання mybranch@{1}посилається на стару фіксацію перед скиданням.

Але якщо ви вже натиснули, див. " Створення гілки git та повернення оригіналу до поточного стану " для інших параметрів.


З Git 2.23 (серпень 2019) , яка була б одна команда: git switch.
А саме:git switch -C mybranch origin/mybranch

Приклад

C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.

Це відновлює індекс і робоче дерево, як git reset --hardби.


Як прокоментував Бред Герман , reset --hardб видалити будь-який новий файл або відновити змінений файл ГОЛОВУ .

Насправді, щоб бути впевненим, що ви починаєте з "чистого шиферу", git clean -f -dпісля скидання це забезпечить робоче дерево точно ідентичне гілці, на яку ви просто скинули.


Ця публікація в блозі пропонує ці псевдоніми ( masterлише для галузей, але ви можете їх адаптувати / розширити):

[alias]
   resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
   resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d

Потім ви можете ввести:

git resetupstream

або

git resetorigin

26
це ВИДАЄТЬСЯ невстановлені / ступані зміни (від --hard)
Peter Ehrlich

5
Я git reset --hard origin/mybranchдекілька разів використовував цю команду, коли мені було байдуже про будь-які локальні зміни і просто хотів чисту копію, яка відповідає походженням. Однак сьогодні це не спрацювало - у мене все ще було кілька нових, нестандартних файлів, і git продовжував обіцяти мені, що це було в HEAD. Примітка про git clean -f -dвиправлене це, витираючи всі нові файли, які я не хотів.
Меттью Кларк

@MatthewClark що , як очікується , см коментар stackoverflow.com/q/4327708/6309
VonC

1
Чудово! Також багато разів я використовував git reset --hard HEADдля повернення до попереднього зобов’язання, ігноруючи будь-які зміни
daronwolff

Чи можливо це також і за допомогою ліцензії?
Лонзак

20

Припустимо, що це сталося:

# on branch master
vi buggy.py                 # you edit file
git add buggy.py            # stage file
git commit -m "Fix the bug" # commit
vi tests.py                 # edit another file but do not commit yet

Потім ви розумієте, що вносите зміни на неправильну гілку.

git checkout -b mybranch    # you create the correct branch and switch to it

Але masterвсе ж вказує на вашу відданість. Ви хочете, щоб він вказав, де він вказував раніше.

Рішення

Найпростіший спосіб:

git branch --force master origin/master

Інший спосіб:

git checkout master
git reset --soft origin/master
git checkout mybranch

Зауважте, що використання reset --hardможе призвести до втрати невмілих змін ( tests.pyна моєму прикладі).


Це здається безпечнішим, ніж у моїй відповіді;) +1
VonC

8

У мене є приватне репо на сервері і регулярно перезавантажувати / натискати на нього, що робить необхідним часто скидати локальну гілку на іншому моєму комп’ютері. Тому я створив наступний псевдонім "підхоплення", який дозволяє робити це для поточної гілки. На відміну від іншої відповіді, у цьому псевдонімі немає назви твердо кодованої гілки.

Тримайся.

[alias]
  catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"

Правильно відформатований (не працюватиме з новинками в .gitconfig), це виглядає приблизно так:

"
!f(){
  echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
  read -r ans;
  if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
    git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
  else
    echo \"catchup aborted\";
  fi
}; f
"
  • \\033[0;33mІ \\033[0mє для виділення поточної гілки і вище з кольором.
  • $(git symbolic-ref -q --short HEAD) - поточна назва філії
  • $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) є вище за течією поточної гілки.

Оскільки скидання - це потенційно небезпечний виклик (особливо з опцією --hard, ви втратите будь-які неспроможні зміни), він спочатку повідомляє вам, що він має робити. Наприклад, якщо ви перебуваєте у відділенні dev-контейнера з віддаленим іменем qcpp / dev-контейнер, і ви введете git catchup, вам буде запропоновано:

скинути dev-контейнер до qcpp / dev-container? (Так / н)

Якщо ви введете y або просто натисніть return, він виконає скидання. Якщо ви введете що-небудь інше, скидання не буде здійснено.

Якщо ви хочете бути надзвичайно безпечними та програматично запобігати втраті нестандартних / невідомих змін, можете додатково згорнути вищезгаданий псевдонім за допомогою перевірок на діф-індекс .

Обов’язкове слово попередження: Якщо ви працюєте над загальнодоступним сховищем, інші люди базуються на роботі, і вам потрібен цей псевдонім, ви робите це неправильно ™ .


1

Я спробував це, і він не скинув мою поточну гілку до моєї віддаленої версії github. Я гуглив і знайшов https://itsyndicate.org/blog/how-to-use-git-force-pull-properly/

який запропонував

git fetch origin master
git reset --hard origin/master

Я хотів скинути свою гілку v8, щоб це зробити

git fetch origin v8
git reset --hard origin/v8

і це спрацювало


Добре, що ви згадуєте про збір. Я зробив це один раз без і скинув усе до 2 років тому :)
Адам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.