Як виправити прихильність до неправильної гілки Git?


621

Я просто зробив цілком непоганий вчинок на неправильній гілці. Як я скасую останню команду у своїй головній гілці, а потім прийняти ті самі зміни та ввести їх у свою гілку оновлення?

Відповіді:


975

Якщо ви ще не натиснули свої зміни, ви також можете змінити скидання:

git reset --soft HEAD^

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

git checkout branch
git commit

Недоліком є ​​те, що вам потрібно повторно ввести повідомлення про фіксацію.


10
зауважте, що м'яке скидання залишає ваші зміни поетапними та готовими до здійснення. мене трохи збентежило, коли мій IDE не показав, що файли повертаються до модифікованого стану після м'якого скидання.
mtjhax

9
ідеальне виправлення, насправді було пару фактів, так що HEAD ^^ і бам все підтягнуто
pablo

8
Дякую. Це врятувало мене двічі. Якщо гілки дещо відрізняються, після скидання та перед оформленням замовлення вам, можливо, доведеться приховати зміни, перш ніж ви зможете отримати іншу гілку. Повторно застосуйте сховище після виїзду
Кірбі

17
Користувачі zsh: вам може здатися, що вам потрібно втекти ^ так:git reset --soft HEAD\^
Стівен Фугрі

54
Якщо ви отримаєте більше? у своєму командному рядку Windows використовуйте лапки для оточення HEAD ^, наприклад: git reset --soft "HEAD ^"
Nate Cook

140

4 роки запізнюємось на цю тему, але це може бути корисним для когось.

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

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

Тепер у вас є головна галузь, дорівнює, origin/masterі всі нові комісії продовжуються my_feature. Зауважте, що my_featureце локальне відділення, а не віддалене.


Дякую за відповідь. Тепер я використовую egit, і мені цікаво, чи зможу я виконати те саме, виконавши наступне: 1) Перейменуйте поточний 'master' на 'my_feature'. 2) Відтворіть місцевий 'master' з 'origin / master'. Я не впевнений, що egit робить під кришкою для цих операцій, але це, здається, є життєздатним рішенням
mjj1409

чому злиття? ви можете створити гілку безпосередньо master, а потім відновити masterдо origin/master.
цезарсол

1
Це найцікавіша частина: вам не потрібна кількість комісій, оскільки origin/masterце вже є зобов'язанням, яке ви хочете скинути! Але заслуга підказки - це ця сторінка: github.com/blog/…
caesarsol

4
Це має бути прийнятою відповіддю. Простий, очевидний, простий, працює незалежно від кількості комітетів і лише використовуючи базовий функціонал Git. Я зробив ці кроки з TortoiseGit. Дякую! :)
Ян Грінґер

1
Я вважав, що це найкраща відповідь, але вона має обмеження. Це допомагає лише в тому випадку, якщо вас нещодавно витягнули з дистанційного. І передбачає, що у вас є пульт для початку. Якщо у вас є лише локальні гілки "master" і ваша нова функція виправлена, єдиною правильною відповіддю є жорсткий перезавантаження майстра підрахунку певної кількості комітетів.
pauljohn32

111

Якщо у вас є чиста (не змінена) робоча копія

Щоб відкатати одну комітку (обов'язково занотуйте хеш коміту для наступного кроку):

git reset --hard HEAD^

Щоб вивести цю комісію в іншу гілку:

git checkout other-branch
git cherry-pick COMMIT-HASH

Якщо ви змінили або відслідковували зміни

Також зверніть увагу на те, що git reset --hardви знищите будь-які зміни, які ви не матимете, і, якщо у вас є ті, які ви могли б віддати перевагу:

git reset HEAD^
git checkout .

git rev-parse BRANCH_NAMEщоб отримати ша.
wilhelmtell

12
Якщо ви забудете спочатку відзначити хеш, просто використовуйте git reflog show <branch>!
Каскабель

2
@Jefromi Мене там на хвилину було страшно.
Ян Хантер

13
Для додаткового безпечного відчуття виконайте вишню спочатку на правильній гілці і лише потім скиньте неправильну гілку.
Вік Муїй

1
Також у випадку невиправлених змін, ви можете git stashперед скиданням і використати їх git stash popпісля відновлення, тому не потрібно боятися --hardчастини
Клеменс Кляйн-Роббенхаар

20

Якщо ви вже натиснули зміни, вам потрібно буде змусити наступний натиск після скидання ГОЛОВИ.

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

Попередження: жорсткий скидання скасує будь-які невідомі модифікації у вашій робочій копії, тоді як силовий натиск повністю замінить стан віддаленої гілки з поточним станом локальної гілки.

На всякий випадок, у Windows (використовуючи командний рядок Windows, а не Bash), насправді чотири ^^^^замість одного, так це

git reset --hard HEAD^^^^

6
Зверніть увагу , що ви повинні НЕ змушувати-поштовх до гілки , що інші люди не використовуючи , якщо це абсолютно необхідно - в іншому випадку вони не зможуть натиснути , поки вони не перебазуватися. Якщо ви єдиний розробник, який використовує git, це все добре.
Блер Холлоуей

2
Або, якщо ви не зрозумієте досить швидко, перш ніж хто-небудь інший витягнув помилкові зобов'язання.
Майкл Міор

Якщо ви скористаєтеся більше ніж одним, ви можете вказати потрібне вам зобов’язання: git reset --hard COMMIT_HASH git push --force
David Cramblett

17

Нещодавно я робив те саме, де я випадково вчинив зміну майстра, коли я мав зобов’язатись до іншої галузі. Але я нічого не штовхав.

Якщо ви просто перейшли на неправильну гілку, і з того часу нічого не змінили, і не перейшли на репо, ви можете зробити наступне:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

ПРИМІТКА: у наведеному вище прикладі я перемотував 1 комітку з git reset HEAD ~ 1. Але якщо ви хотіли перемотати n команд, то ви можете зробити git reset HEAD ~ n.

Крім того, якщо ви вирішили скористатися неправильною гілкою, а також написати ще якийсь код, перш ніж зрозуміти, що ви скористалися невірною гілкою, тоді ви можете використовувати git stash для збереження вашої незавершеної роботи:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

ПРИМІТКА. Я використовував цей веб-сайт як посилання https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/


Подібне трапилося і зі мною, я здійснив кілька змін у магістра, але я мав би зробити в новій гілці та відправити PR, я в кінцевому підсумку просто робив git checkout -b new_branchправо звідти, комісії були недоторканими, просто штовхнув і створив PR, не став ' не доведеться знову вчиняти.
Ніщал Гаутам

11

Отже, якщо ваш сценарій полягає в тому, що ви взяли на себе зобов’язання, masterале маєте намір взяти на себе зобов'язання another-branch(яке може бути, а може і не існувати), але ви ще не наполягали на цьому, це досить легко виправити.

// if your branch doesn't exist, then add the -b argument 
git checkout -b another-branch
git branch --force master origin/master

Тепер усі ваші зобов'язання masterбудуть продовжуватися another-branch.

Захоплений коханням від: http://haacked.com/archive/2015/06/29/git-migrate/


здається, найпростіший підхід! Не впевнений, чому так мало кохання і переживає
keligijus

4
Це, здається, не спрацювало для мене. another-branchвже існували. У цьому випадку це просто занурило зобов’язання, які я зробив для освоєння, і не поклав їх на себе another-branch.
Жизель Серате

6

Детальніше про цю відповідь, якщо у вас є кілька переходів, наприклад, developдо new_branch:

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started

1
У мене було три комісії для повернення, і це питання, схоже, витягнуло мою дупу з вогню. Дякую!
holdenweb

3

Якщо ви зіткнулися з цією проблемою і у вас є Visual Studio, ви можете зробити наступне:

Клацніть правою кнопкою миші на вашу гілку та виберіть View History:

введіть тут опис зображення

Клацніть правою кнопкою миші на фіксацію, до якої ви хочете повернутися. І поверніть або скиньте, якщо потрібно.

введіть тут опис зображення


3

Для декількох комісій на неправильній гілці

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

Що ви могли зробити, і що мене врятувало, використовуючи цю відповідь як орієнтир, використовуючи 4-х етапний процес, який є -

  1. Створіть нову тимчасову гілку з master
  2. Злиття у галузь, спочатку призначена для комітетів, тобто branch_xyz
  3. Скасувати посилання на master
  4. Видаліть тимчасову гілку.

Ось описані вище кроки в деталях -

  1. Створіть нову гілку з master(де я випадково вніс багато змін)

    git checkout -b temp_branch_xyz
    

    Примітка: -bпрапор використовується для створення нової гілки.
    Просто для того, щоб перевірити, чи отримали ми це право, я би швидко git branchзробив, щоб переконатися, що ми знаходимось на temp_branch_xyzгілці, і git logперевірити, чи правильно ми здійснили комісію.

  2. Об’єднати тимчасову гілку у гілку, спочатку призначену для комітетів, тобто branch_xyz.
    По-перше, перейдіть на початкову гілку, тобто branch_xyz(можливо, вам знадобиться, git fetchякщо ви цього не зробили)

    git checkout branch_xyz
    

    Примітка. Не використовується -bпрапор.
    Давайте об’єднаємо тимчасову гілку з гілкою, яку ми наразі перевіряємоbranch_xyz

    git merge temp_branch_xyz
    

    Можливо, вам доведеться подбати про якісь конфлікти тут, якщо вони є. Після успішного злиття ви можете натиснути (я б) або перейти до наступних кроків.

  3. Скасуйте випадкові зобов’язання masterвикористовувати цю відповідь як орієнтир, спочатку перейдіть наmaster

    git checkout master
    

    потім скасуйте його до кінця назад, щоб відповідати віддаленому (або до певної фіксації, якщо хочете)

    git reset --hard origin/master
    

    Знову ж таки, я б робив git logдо і після лише переконання, що намічені зміни вступили в силу.

  4. Видалення доказів, тобто видалення тимчасової гілки. Для цього спочатку вам потрібно перевірити гілку, у яку було злито темп, тобто branch_xyz(Якщо ви залишаєтесь masterта виконайте команду нижче, ви можете отримати error: The branch 'temp_branch_xyz' is not fully merged), тож давайте

    git checkout branch_xyz
    

    а потім видаліть підтвердження цієї невідповідності

    git branch -d temp_branch_xyz
    

Ось так.


1

Якщо гілка, до якої ви хотіли застосувати ваші зміни, вже існує (наприклад, розробка гілки ), дотримуйтесь вказівок, які були надані фотаном нижче, то:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

І очевидно, ви можете використовувати tempbranch або будь-яку іншу назву гілки замість my_feature, якщо хочете.

Також, якщо це застосовно, відкладіть приховану скриньку (застосувати) до тих пір, поки ви не зробитеся з цільовою гілкою.


Я думаю, що перша команда (розробка замовлення) не є потрібною ... ребайна буде просто перевірити "my_feature", як перше, що вона робить.
JoelFan

Також ви можете залишити параметр "my_feature" команди "rebase" (оскільки ви вже перевірили "my_feature"). ви також можете залишити параметр "розвивати" параметри "злиття" (оскільки ви вже
замовляєте

1

Для мене це було вирішено шляхом повернення комітету, який я підштовхнув, а потім вибору вишень, який виконується в іншій галузі.

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

Ви можете використовувати git logправильний хеш, і ви можете натискати ці зміни, коли завгодно!

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