Як додати змінений файл до старшої (не останньої) комісії в 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.