Як додати змінений файл до старшої (не останньої) комісії в Git


461

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

Журнал виглядає приблизно так:

    GIT TidyUpRequests u:1 d:0> git log 
    commit fc6734b6351f6c36a587dba6dbd9d5efa30c09ce 
    Author: David Klein <> 
    Date:   Tue Apr 27 09:43:55 2010 +0200

        The Main program now tests both Webservices at once

    commit 8a2c6014c2b035e37aebd310a6393a1ecb39f463 
    Author: David Klein <>
    Date:   Tue Apr 27 09:43:27 2010 +0200

        ISBNDBQueryHandler now uses the XPath functions from XPath.fs too

    commit 06a504e277fd98d97eed4dad22dfa5933d81451f 
    Author: David Klein <> 
    Date:   Tue Apr 27 09:30:34 2010 +0200

        AmazonQueryHandler now uses the XPath Helper functions defined in XPath.fs

    commit a0865e28be35a3011d0b6091819ec32922dd2dd8 <--- changed file should go here
    Author: David Klein <> 
    Date:   Tue Apr 27 09:29:53 2010 +0200

        Factored out some common XPath Operations

Будь-які ідеї?


Відповіді:


694

Використовуйте git rebase. Конкретно:

  1. Використовуйте git stashдля зберігання змін, які ви хочете додати.
  2. Використовуйте git rebase -i HEAD~10(або скільки завгодно запитів, які ви хочете побачити).
  3. Позначте компіляцію ( a0865...) для редагування, змінивши слово pickна початку рядка на edit. Не видаляйте інші рядки, як це видалило б коміти. [^ Vimnote]
  4. Збережіть файл бази даних, і git повернеться до оболонки і чекатиме, коли ви виправите цю фіксацію.
  5. Розмістіть скриньку, використовуючи git stash pop
  6. Додайте файл за допомогою git add <file>.
  7. Змініть посилання на git commit --amend --no-edit.
  8. Виконайте те, git rebase --continueщо перепише решту ваших зобов’язань проти нового.
  9. Повторіть дії з кроку 2, якщо ви позначили кілька змін для редагування.

[^ vimnote]: Якщо ви користуєтесь, vimвам доведеться натиснути Insertклавішу для редагування, а потім Escвведіть, :wqщоб зберегти файл, вийти з редактора та застосувати зміни. Крім того, ви можете налаштувати зручний редактор git commit з git config --global core.editor "nano".


23
Що робити, якщо у вас є нестандартні зміни, які ви хочете додати до редагування? Якщо я їх приховую, я не міг би git add.
— Сем

15
Сам, ви можете просто видалити зміни, перебуваючи на комісії, про який йдеться, це буде добре.
— omnikron

17
Примітка. Коли ви позначаєте комісію за допомогою edit, НЕ ВИДАЛУЙТЕ інші зобов'язання, перелічені у файлі. Якщо ви це зробите, комісії буде видалено, і вам потрібно буде виконати ці кроки, щоб повернути їх.
— Девід Туїт

2
Що стосується того, що сказав @DavidTuite, моя звичка, коли я роблю речі на git, я не знаю, як вийде, - це створення гілки "branchname-ref" для збереження поточного стану часової шкали у випадку, якщо я накручую речі. Коли я закінчую, я видаляю його.
— Рафаель

1
На етапі 6 включіть. (крапка) в команді. Правильна команда:git add .
— Том

323

Щоб "виправити" стару фіксацію з невеликою зміною, не змінюючи повідомлення про фіксацію старого комітету, де OLDCOMMITє щось на зразок 091b73a:

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

Ви також git commit --squash=OLDCOMMITможете редагувати старе повідомлення про фіксацію під час перезавантаження.


  • git rebase --interactiveвиведе текстовий редактор (який можна налаштувати ) для підтвердження (або редагування) послідовності інструкцій відновлення . У файлі є інформація про зміни інструкцій щодо ребаза ; просто збережіть і закрийте редактор ( :wqвvim ), щоб продовжити ребазу.
  • --autosquashавтоматично розмістить будь-які --fixup=OLDCOMMITкомісії в потрібному порядку. Зверніть увагу, що --autosquashце дійсно лише тоді, коли використовується --interactiveпараметр.
  • ^В OLDCOMMIT^допомоги це посилання на Комміт безпосередньо перед OLDCOMMIT.

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

Див. Git commit та git rebase . Як завжди, переписуючи історію git , ви повинні лише виправляти або скріплювати комісії, які ви ще не опублікували нікому іншим (включаючи випадкових користувачів Інтернету та сервери побудови).


18
Набагато чіткіше за інші варіанти, і це спрацювало як принадність
— Кріс Мітчелмор

5
@Jonah: редактор відкритий не для редагування повідомлення про фіксацію , а для підтвердження (або редагування) кроків відновлення бази даних . Цього не уникнути; --autosquashдіє лише тоді, коли використовується --interactiveопція .
— Джоел Пурра

5
Використовуючи це рішення, я застряг git показуючи VIM. Моя проблема полягає в тому, що я не знаю, як використовувати VIM. Як чорт я вибираю з цього, як я можу контролювати цю річ, це так заплутано.
— Неонова Варга

2
@NeonWarge: редактор вибору можна налаштувати, наприклад, використовуючи git config --global core.editor "pico". Існує декілька інших способів налаштування git та / або зміни редактора за замовчуванням і т.д.
— Джоель Пурра

2
один
— рядовий

61

з git 1.7 є дуже простий спосіб використання git rebase:

інсценіруйте свої файли:

git add $files

створіть нове фіксування та повторно використовуйте повідомлення про фіксацію вашої "зламаної" фіксації

git commit -c master~4

додайте fixup!до теми теми (або squash!якщо ви хочете відредагувати фіксацію (повідомлення)):

fixup! Factored out some common XPath Operations

використовувати git rebase -i --autosquashдля закріплення вашої комісії


2
+1. Nice використання нової директиви FixUp (1.7+): stackoverflow.com/questions/2302736/trimming-git-checkins / ...
— VonC

@knittl Я намагався ваш метод додати ще один файл до старого мого фіксатора (не натискається), але при перезапуску я отримую, You asked me to rebase without telling me which branch you want to rebase against, and 'branch.master.merge'і якщо я потім використовую, git rebase -i --autosquashя просто отримую noopтему, повертаючи комісію на себе. Будь-яка ідея, що я роблю неправильно?
— oschrenk

7
@oschrenk: Вам потрібно надати зобов’язання, на яке ви хочете git rebase -i --autosquash HEAD~10
— відновити базу даних

1
Хороша відповідь, але мені також потрібно було додати зобов’язання, на яке слід здійснити базування. Було б чудово, якби ви могли оновити його.
— Пол Одеон

@PaulOdeon: Я не розумію вашого запитання. Що ви намагаєтеся зробити, і де виникають проблеми?
— knittl

8

Ви можете спробувати rebase --interactiveсеанс, щоб змінити свою стару комісію (за умови, що ви вже не пересилали ці зобов'язання до іншого репо).

Іноді річ, зафіксована в б.2. не може бути змінено на не зовсім ідеальну фіксацію, яку вона виправляє, тому що ця фіксація заглиблена глибоко в серії патчів .
Саме для цього призначена інтерактивна база даних: використовувати її після безлічі "a" s та "b" s, переставивши та відредагувавши коміти, і розбивши декілька команд в одну.

Почніть це з останнього зобов'язання, яке ви хочете зберегти як є:

git rebase -i <after-this-commit>

Редактор буде звільнений від усіх комісій у вашій поточній галузі (ігноруючи об'єднання об'єднань), які з’являються після даної фіксації.
Ви можете змінити порядок комісій у цьому списку до вмісту вашого серця, а ви можете їх видалити. Список виглядає приблизно так:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Описи в одній лінії призначені виключно для вашого задоволення; git rebase не буде дивитись на них, а на імена комітів ("deadbee" та "fa1afe1" у цьому прикладі), тому не видаляйте та не редагуйте імена.

Замінивши команду "вибрати" командою "редагувати", ви можете сказати git rebase припинити після застосування цього комітету, щоб ви могли редагувати файли та / або повідомлення про фіксацію, вносити зміни до комісії та продовжувати повторне використання .

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