Як я можу зняти останній коміт у сховищі git bare?


91

Беручи до уваги, що існує декілька команд git, які не мають сенсу в голому сховищі (оскільки голі сховища не використовують індекси та не мають робочого каталогу),

git reset --hard HEAD^ 

не є рішенням скасувати останню зміну в такому сховищі.

Шукаючи в Інтернеті, все, що я міг знайти, пов’язане з цією темою, - це те , в чому мені представлені три способи зробити це:
1. "оновити посилання вручну (що передбачає сантехніку)";
2. " git push -fз неоголеного сховища";
3. " git branch -f this $that".

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


8
@ Lavinia-Garbriela Dobrovol Не використовуйте складні речі нижче. Ви намагаєтесь перемістити HEAD в інший коміт, і саме для цього призначений Git reset, навіть у голому репо. Відповідно до моєї відповіді нижче, використовуйте: git reset --soft <commit> За допомогою --soft ви не намагаєтесь змінити робоче дерево та індекс, який не існує, тому git дозволяє вам скинути без проблем.
Хазок

Відповіді:


130

Ви можете скористатися git update-refкомандою. Щоб видалити останню фіксацію, ви повинні використовувати:

$ git update-ref HEAD HEAD^

Або якщо ви не знаходитесь у гілці, з якої неможливо видалити останній коміт:

$ git update-ref refs/heads/branch-name branch-name^

Ви також можете передати sha1, якщо хочете:

$ git update-ref refs/heads/branch-name a12d48e2

Дивіться документацію до команди git-update-ref .


@ Лавінія-Габріела Добровольскі: так, я не був знайомий з точним синтаксисом.
VonC

@VonC Ви можете вказати <ref> в git update-ref <ref> <newvalue>як правильну гілку, наприклад, "refs / heads / master" замість HEAD, наприклад. Сподіваюсь, я не зрозумів вашого питання.
Лавінія-Габріела Добровольскі

@Sylvain: +1 хороша редакція. @ Lavinia-Gabriela Dobrovolschi дякую за точність. Це набагато практичніше (якщо ви маєте прямий доступ до віддаленого сервера, я припускаю).
VonC

3
Приклади оманливі щодо branch-nameаргументу. При використанні update-refз “гілкою” ви обов’язково повинні вказати повне посилання на назву гілки (тобто додавати refs/heads/до звичайного короткого імені гілки). Якщо ви просто використовуєте коротку назву, то в кінцевому підсумку ви створите / оновите $GIT_DIR/branch-nameзамість $GIT_DIR/refs/heads/branch-name. Існування обох branch-nameі refs/heads/branch-nameпризведе до попередження "перейменувати ... є неоднозначним".
Кріс Джонсен,

Ця відповідь набагато складніша за запропоновану Заком. І його рішення працює чудово.
Кристян

32

Якщо ви використовуєте наступне в голому репо:

git reset --soft <commit>

тоді ви не стикаєтесь із проблемами, які ви використовуєте, --hardта --mixedпараметрами в голому репо, оскільки ви не намагаєтесь змінити щось, що у голого репо немає (тобто робоче дерево та індекс). У вашому випадку конкретно ви хотіли б використовувати (з оголеного репо):

git reset --soft HEAD^

Щоб переключити гілки на віддаленому репо :

git symbolic-ref HEAD refs/heads/<branch_name>

Щоб переглянути поточну вибрану гілку, використовуйте:

git symbolic-ref HEAD

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html


3
Як вибрати гілку, яку потрібно перемістити? Ваш приклад чудово працює на майстрі, але git checkout other_branchпрацює не голий.
Готьє

1
Хм-м-м ... Мені цікаво, хто мене проголосував проти цього. Питання не задавало питання про те, як переключити гілки на віддалене репо, а питання про те, як скинути налаштування на оголеному репо. Щоб змінити гілку за замовчуванням у віддаленому репо, використовуйте git symbolic-ref HEAD refs / heads / <branch_name>.
Хазок

7

The git push -fмає працювати нормально:
якщо ви клонуєте це оголене репо, видаліть останній коміт ( git reset --hard HEAD^як ви вже згадували, але в локальному неголому репо) і натисніть назад ( -f):

  • ви не змінюєте SHA1 для інших комітів, що передують тому, який ви видаляєте.
  • ви впевнені, що відштовхуєте точний вміст оголеного репо за мінусом додаткового коміту (адже ви тільки що клонували його першим).

@ VonC Привіт Von, я бачив, як ти багато відповідаєш на Git, тому я хотів запитати тебе ... Мені було цікаво, чому б, git reset --soft <sha1>як показано в моїй відповіді нижче, не було рекомендованою практикою переміщення HEAD на оголеному репо?
Хазок,

Я думаю, ще однією причиною, яку я запитую, є те, що використання м'якого скидання для оголених репо не є доступною інформацією, і багато форумів, здається, мають надмірно складні обхідні шляхи, коли, здається, м'яке скидання є найкращою практикою через найменшу кількість набору тексту та найменші шанси за помилку.
Хазок,

2
@Zach: a reset --softповинен працювати, коли це робиться безпосередньо на оголеному репо. Я підозрюю, що це робиться рідко, оскільки оголене репо - це, як правило, попереднє репо (тобто репо, до якого ви надсилаєте дані), і більшу частину часу у вас немає прямого локального доступу до нього. Але якщо ви це зробите, це, безумовно, ще один хороший приклад reset --softвикористання ("як у stackoverflow.com/questions/5203535/… ) Отже, +1 до вашої відповіді.
VonC

2

Ви також можете використовувати нотацію git refspec і зробити щось подібне:

git push -f origin +<commit you want to revert to>:<destination_head | branch_name>

Це змушує оновити гілку призначення (як позначено посиланням) до коміту джерела, як позначено +<object ref>частиною.


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