Видаліть файли з фіксації Git


1612

Я використовую Git, і я створив декілька файлів, використовуючи

git commit -a

Пізніше я виявив, що файл був помилково доданий до комітету.

Як я можу видалити файл з останньої фіксації?


2
Це посилання ідеально підходить для Вашого питання: stackoverflow.com/questions/307828 / ...
b3h3m0th

@CharlesB: так, це мій останній вчинок
Лоллі

8
у вас підштовхнув зобов’язання до сервера?
Парітош Сінгх

4
Я просто роблю це, використовуючи:git reset filepath
felipekm

Відповіді:


3087

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

git reset --soft HEAD^ 

або

git reset --soft HEAD~1

Потім скиньте небажані файли, щоб не вилучити їх:

git reset HEAD path/to/unwanted_file

Тепер знову покладіть команду, навіть можете повторно використовувати те саме повідомлення про фіксацію:

git commit -c ORIG_HEAD  

86
Дякую за це Варто додати, що якщо ви вже підштовхнули свою попередню (неправильну) команду, а тепер спробуйте git pushвиправити її до репо, вона поскаржиться Updates were rejected because the tip of your current branch is behind its remote counterpart.. Якщо ви впевнені, що хочете натиснути на них (наприклад, це ваша виделка), тоді ви можете скористатися -fопцією для натискання, наприклад git push origin master -f. (Не робіть цього до репо за течією, з якої
добираються

57
git reset --soft HEAD^це моя найпоширеніша операція скасування
funroll

2
@PabloFernandez, перш за все, прийнятою відповіддю могло бути те, що шукала ОП (Крім того, вона була розміщена місяцями раніше). По-друге, прийняті відповіді завжди стоять на вершині незалежно від кількості голосів.
MITjanitor

4
@PabloFernandez вгорі всіх відповідей - це три вкладки, які дозволяють контролювати впорядкованість відповідей: активні , найстаріші та голоси . Я здогадуюсь, ваша, встановлена найдавнішою . Переключіть його на голоси, хоча прийнята відповідь все ще буде вгорі, ця відповідь буде другою.
ahsteele

15
Я багато про це знав, git resetале хотів, якби вплинути на існуючий комітет "на місці". Я щойно дізнався про це git commit -C. Тож для мене те, що я хочу, - це ваш точний рецепт з ще одним кроком, прописаний як «новий вчинок знову» git commit -C [hash of original HEAD commit from first step].
метамат

323

УВАГА ! Якщо ви хочете лише видалити файл із попереднього комітету та зберегти його на диску , прочитайте відповідь juzzlin трохи вище.

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

  1. видаліть файл git rm <file>
  2. погодити прапор із зміною: git commit --amend

Прапор поправки говорить git знову здійснити, але "об'єднати" (не в сенсі злиття двох гілок) цю команду з останньою командою.

Як зазначено в коментарях, використання git rmтут - це як використання самої rmкоманди!


120
ви також можете використовувати git rm --cachedдля збереження файлів на диску
Аркадій Кукаркін

14
Попередження для тих, хто переглядає цю відповідь: переконайтесь, що ви хочете ВИДАЛИТИ файл (як у минулому!), А не просто видаляти його зі списку «Коміт».
Скотт Біггс

8
Для того, щоб додати до того , що говорять інші (і зробити його легше запам'ятати , щоб не робити цього , якщо ви дійсно хочете): в команді буде робити те , що саме по собі робить! rmgitrm
йо

@CharlesB Чи можете ви, будь ласка, додати примітку з коментаря Аркадія Кукаркіна до своєї відповіді, щоб надати їй більшої наочності?
mopo922

2
Зауважте, що файли все ще можна відновити, якщо ви передумали, команда перед цим git commit --amendвсе ще існує і може бути знайдена, наприклад, з git reflog. Тож це не так вже й погано, як підказують інші коментарі.
Стеохан

165

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

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

1.

Знайдіть комітку, якій ви хочете, щоб файл відповідав.

git checkout <commit_id> <path_to_file>

це можна зробити кілька разів, якщо ви хочете видалити багато файлів.

2.

git commit -am "remove unwanted files"

3.

Знайдіть commit_id комісії, на якій файли були додані помилково , скажімо, тут "35c23c2"

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

Ця команда відкриває редактор відповідно до ваших налаштувань. Типовим є vim.

Перемістіть останню команду, яка має бути "видалити непотрібні файли", до наступного рядка неправильної фіксації ("35c23c2" у нашому випадку) та встановіть команду як fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Ви повинні бути гарними після збереження файлу.

Закінчувати :

git push -f

Якщо у вас, на жаль, виникають конфлікти, вам доведеться їх вирішувати вручну.


2
Робити це з нано - казково! Ctrl + K, Ctrl + U, поставте 'f', Ctrl + X, поставте 'y' і voila!
продовження

6
Якщо ви хочете фактично видалити файли з репо (не з файлової системи), а не просто повернути їх до попередньої версії, то замість кроку 1 зробіть git rm --cached <file(s)>.
waldyrious

2
Зачекаєте, що ви можете просто перемістити коміти по файлу інтерактивного ребазування за бажанням?
Дан Розенстарк

2
Ви цілком можете, але можете (а може і не) отримати конфлікти.
Брайан

6
Цей процес можна було б трохи спростити, додавши --fixup=35c23c2до git commitкоманди. Це дозволить автоматично встановити фіксацію як фіксацію необхідної фіксації, і тому вам не потрібно буде вказувати її в ребазі. Крім того, якщо ви додасте --autosquashдо git rebaseкоманди, git автоматично перемістить ваш комітет у потрібне місце, тому вам не потрібно нічого робити в інтерактивній базі даних - просто збережіть результат (це означає, що вам навіть не потрібно -iпозначити прапор, хоча я люблю використовувати його так чи інакше, щоб переконатися, що все виглядає так, як я очікую)
Guss

144

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

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

git resetБуде приймати файл , як це було в попередній фіксації і стадії його в індексі. Файл у робочому каталозі недоторканий.
Тоді git commitзаповіт буде скоєно та розбити індекс на поточний.

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


5
Це набагато краща відповідь на видалення лише одного файлу без ремонту всього комітету.
nimish

Це точно так само , як і ця відповідь: D stackoverflow.com/a/27340569/1623984
ThatsAMorais

@ThatsAMorais дійсно :-). Мені цікаво, чи це питання злилося з іншим, і тому я цього не бачив. А може, я просто сліпий. У будь-якому випадку, я думаю, що я схильний залишити це як на основі голосів, що здається більш популярним (можливо, люди вважають за краще коротку та пряму відповідь).
Патрік

В будь-якому випадку залиште це! :) У нас явно була правильна ідея, а мета - допомогти. Я думаю, що об'єднання - це хороша теорія.
ThatsAMorais

Як це зробити, якщо ти вже натиснув на гілку на github? Я намагався натиснути після цього виправлення і отримав повідомлення "Оновлення було відхилено, тому що підказка вашої поточної гілки знаходиться за підказкою: її віддалений аналог".
Оллі Вільямс

41

Якщо ви не натиснули зміни на сервері, ви можете використовувати

git reset --soft HEAD~1

Він скине всі зміни та повернеться до одного повернення

Якщо ви змінили свої зміни, виконайте дії, відповіді на @CharlesB


2
Скидання -1 git видаляє файл змін, які відбулися, з області постановки, тут зміна здійснена
CharlesB

Гаразд, але я буду тримати свою заяву, оскільки це не те, чого хочуть ОП :) Вибачте
CharlesB

ОК, це добре для мене, але чому опонент цього не хоче. В чому проблема?
Парітош Сінгх

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

3
@Aris використовуйте <git diff --cached>, щоб побачити зміни
Paritosh Singh

37

Видалення файлу за допомогою rm видалить його!

Ви завжди додаєте команду в git, а не видаляєте, тому в цьому випадку поверніть файл у стан, у якому він був до першої фіксації (це може бути дія "rm", якщо файл новий), а потім повторно введіть і файл піде.

Щоб повернути файл у попередній стан:

    git checkout <commit_id> <path_to_file>

або повернути його в стан у віддаленій ГОЛОВІ:

    git checkout origin/master <path_to_file>

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


36
git checkout HEAD~ path/to/file
git commit --amend

1
Це найкращий спосіб змінити останню команду, ту, яку не було натиснуто. Це скине зміни в одному файлі, фактично видаливши цей файл з останнього комітету.
Алекс Браво

Це також змінило файл. Як зберегти локальні зміни у файлі?
theonlygusti

29

Далі буде нестабільним лише той файл, який ви задумали, про що запитав ОП.

git reset HEAD^ /path/to/file

Ви побачите щось таке:

Зміни, які слід вчинити: (використовуйте "git reset HEAD ..." до нестабільності)

змінено: / шлях / до / файл

Зміни, не встановлені для фіксації: (використовуйте "git add ..." для оновлення того, що буде здійснено) (використовуйте "git checkout - ...", щоб відмовити зміни в робочому каталозі)

змінено: / шлях / до / файл

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

У цей момент ви можете робити все, що завгодно до файлу, наприклад, перезавантаження на іншу версію.

Коли ви готові взяти на себе зобов’язання:

git commit --amend -a

або (якщо у вас відбуваються якісь інші зміни, які ви не хочете здійснювати)

git commit add /path/to/file
git commit --amend

3
Відповідь juzzlin чудова, але її надмірна нестабільність всього комітету, коли ви хочете лише зняти його. Видалення цілої комісії може спричинити проблеми, якщо ви невстановили зміни в файлах, які ви не хочете втрачати.
ThatsAMorais

27

Я поясню вам на прикладі.
Нехай A, B, C - 3 послідовних передачі. Комісія B містить файл, який не повинен був бути скоєний.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    

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

Для одного скоєння, зміни noopв edit [A_commit_ID]абоe [A_commit_ID]
TamusJRoyce

23

Можна просто спробувати.

git reset --soft HEAD~1

і створити новий комітет.

Однак є дивовижне програмне забезпечення "gitkraken". що полегшує роботу з git.


1
І лише зауважте: після цього вам слід git commit --amendбуде оновити видалення файлу в останньому фіксації; а згодом ви можете перевірити, чи дійсно його видаленоgit log -1 --stat
sdbbs

13
git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

залишить вам локальний файл все одно. Якщо файл також не потрібно локально, ви можете пропустити параметр --cached.

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

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

і тоді ви можете легко закінчити базу даних, не запам'ятовуючи більш складні команди або виконуючи повідомлення або вводити стільки.


Це працює для мене. Я припускаю, що якщо ви хочете додати файли назад у суміш, просто використовуйте git add -A або git add. і вони повернулися.
Олександр Міллс

11

Використання графічного інтерфейсу git може спростити видалення файлу з попередньої фіксації.

Якщо припустити, що це не спільна гілка, і ви не проти переписувати історію , то запустіть:

git gui citool --amend

Ви можете скасувати перевірку файлу, який був помилково скоєний, і натисніть кнопку "Ввести".

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

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


2
На Ubuntu ви можете встановити git gui за допомогоюsudo apt-get install git-gui
JDiMatteo

Дякую! У мене виникла проблема (помилка?), Де додана папка, що містить .git repo, і всі регулярні команди видалення не працювали. Це, однак, допомогло. Будучи декількома поверненнями, я спершу використав, git rebase -i HEAD~4а потім запустив вашу команду, щоб відкрити редактор. Ще одна примітка: "Зняття налаштувань" можна знайти в меню "Зняти".
Джонні Сковдал

Найпростіше рішення з усіх. Найпростіше запам’ятати. І набагато менше схильних до помилок, ніж використання git reset --soft HEAD^(пам’ятаючи аргумент --soft Software), за яким слідує git commit -c ORIG_HEAD(а не --amend, який все накручує).
Brent Faust

9

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

git checkout origin/<remote-branch> <filename>
git commit --amend

6

Виконайте послідовність з наступних команд:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'

Я намагався виконати ці кроки, і я бачу цю помилку помилки: не вдалося натиснути кілька посилань на 'git ....'. Щоб запобігти втраті історії, відхилені нешвидкі перемотки вперед Об’єднайте віддалені зміни (наприклад, 'git pull') перед натисканням знову. Докладніше див. У розділі "Примітка про швидке перемотування вперед" розділу "git push --help". (після витягування git у мене ті ж зміни)
Dezigo

Це означає, що стан вашого віддаленого репо змінився, поки ви виконували свою місцеву роботу. І після "git pull" ваші локальні зміни слід об'єднати з віддаленими, ось і все. Звичайно, ваші зміни повинні залишитися.
Сергій Онищенко

Іншими словами, якщо ви отримаєте помилку @Dezigo, додайте прапор -f, щоб примусити оновити.
jungledev

5

Просто хотів доповнити верхню відповідь, оскільки мені довелося виконати додаткову команду:

git reset --soft HEAD^
git checkout origin/master <filepath>

Ура!


Ласкаво просимо. Ця відповідь буде краща, якби ви пояснили, що насправді виконують команди.
Марк Чорлі

3

Щось, що працювало для мене, але все-таки думаю, що має бути краще рішення:

$ git revert <commit_id>
$ git reset HEAD~1 --hard

Просто залиште зміну, яку ви хочете скасувати в іншій комісії, перевірте інші

$ git commit --amend // or stash and rebase to <commit_id> to amend changes

3

git reset --soft HEAD^повертає назад ваше зобов’язання, і коли ви набираєте git status, він говорить вам, що робити:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

2

Насправді, я думаю, що більш швидкий і простий спосіб - це використовувати інтерактивний режим git rebase.

git rebase -i head~1  

(або голова ~ 4, як завжди ви хочете піти)

а потім замість "вибору" використовуйте "редагувати". Я не усвідомлював, наскільки потужна «редакція».

https://www.youtube.com/watch?v=2dQosJaLN18

Сподіваюся, вам це стане в нагоді.


це відео 10 хвилин і не настільки корисне
MolbOrg

2

Була така сама проблема, коли я маю зміни в місцевій гілці, де я хотів відновити лише один файл. Що для мене працювало -

( функція / target_branch нижче - це те, де я змінив усі зміни, включаючи ті, які хотів скасувати для конкретного файлу)

( походження / особливість / target_branch - це віддалена гілка, куди я хочу натиснути свої зміни)

( функція / постановка - це моя тимчасова гілка постановки, де я буду натискати на всі потрібні зміни, виключаючи зміни до цього одного файлу)

  1. Створіть локальну гілку з мого походження / особливості / target_branch - її називають функцією / інсценізацією

  2. Об'єднаної мій робочий місцеве відділення функції / target_branch до функції / постановка філії

  3. Перевірено функцію / постановку, а потім скинути git --soft ORIG_HEAD (Тепер усі зміни функції / інсценізації 'будуть інсценізовані, але не виконані.)

  4. Незазначений файл, який я раніше зареєстрував, із зайвими змінами

  5. Змінено гілку вгору за течією для функції / постановки на початок / особливість / target_branch

  6. Решту поетапних змін здійснив і перемістив уверх по потоку до мого віддаленого походження / функції / target_branch


1

Якщо вам цей файл більше не потрібен, ви можете це зробити

git rm file
git commit --amend
git push origin branch

1

Якщо ви використовуєте GitHub і ще не натиснули на зобов'язання, GitHub Desktop вирішує цю проблему легко:

  1. Виберіть Репозиторій -> Скасувати останні записи
  2. Видаліть файл, який ви помилково додали. Попереднє повідомлення про фіксацію вже буде у діалоговому вікні.
  3. Натисніть кнопку "Ввести"!

1

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

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'

Якщо ви бачите цю помилку:

Неможливо створити нову резервну копію. Попередня резервна копія вже існує у refs / original / Force, що перезаписує резервну копію на -f

Просто видаліть резервні копії оновлень на локальному репо

$ rm -rf .git/refs/original/refs

1

якщо ви ще не натискаєте свої зміни на git

git reset --soft HEAD~1

Він скине всі зміни та повернеться до одного повернення

Якщо це останнє зобов’язання, яке ви здійснили, і ви хочете видалити файл з локального та віддаленого сховища, спробуйте це:

git rm <file>
 git commit --amend

а ще краще:

скинути спочатку

git reset --soft HEAD~1

скинути непотрібний файл

git reset HEAD path/to/unwanted_file

здійснити знову

git commit -c ORIG_HEAD  

це те саме, що вище, але навіть справді допомогло перехрестити
Решма

0

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

git checkout origin/develop <path-to-file>
git add <path-to-file>
git commit -m "Message"
git push

0

Я скопіював поточні файли в іншу папку, а потім позбувся всіх незапущених змін:

git reset --hard @{u}

Потім скопіюйте речі назад. Здійсни, поштовх.



0
Here is the step to remove files from Git Commit.

>git reset --soft HEAD^1(either commitid ) -- now files moved to the staging area.
>git rm --cached filename(it will removed the file from staging area)
>git commit -m 'meaningfull message'(Now commit the required files)

-1

Наразі жодна з відповідей не є розумною. Здається, що достатньо попиту запропонувати реальне рішення: https://github.com/git/git/blob/master/Documentation/SubmittingPatches

git - uncommit <ім'я файлу>

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

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