Як зняти велику кількість файлів без видалення вмісту


454

Я випадково додав багато тимчасових файлів за допомогою git add -A

Мені вдалося зняти файли за допомогою наступних команд і вдалося видалити брудний індекс.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Вищезазначені команди перелічені у розділі git help rm. Але, на жаль, мої файли також були видалені під час виконання, хоча я дав можливість кешу. Як я можу очистити індекс, не втрачаючи вміст?

Також було б корисно, якщо хтось може пояснити спосіб роботи цієї труби.


8
rm -fне є командою git і не має --cachedможливості. Ваші локальні файли були видалені перед виконанням, git rmтому я не думаю, що ви можете законно звинувачуватись git rmу чомусь.
CB Bailey

8
@sarat, будь ласка, подумайте про те, щоб змінити правильну відповідь на висококваліфіковану відповідь від Ian Maddox , оскільки git reset --hardце не правильна відповідь і фактично видалить вміст. Це збентежить користувачів - як і я.
Марко Пашков

2
@sarat як каже Марко, продовжуй. Ця сторінка отримує багато трафіку.
Росс

@MarcoPashkov & Ross дякую хлопці. Зроблено.
сарат

Відповіді:


986

git reset

Якщо все, що ви хочете, - це скасувати надмірний запуск "git add":

git reset

Внесені вами зміни будуть нестандартними і готові повторно додати їх за вашим бажанням.


НЕ РУБАЙТЕ git reset --hard.

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


15
Я завдячую тобі пінту Ian
DasBooten

1
Я часто знаходжу , що я повинен виконати git checkout -- *, а
Den-Jason

1
Ви зекономили багато зусиль. Людина подяки
RajnikantDixit

35

Якщо у вас є незаймане репо (або HEAD не встановлено) [1], ви можете просто

rm .git/index

Звичайно, це зажадає від вас повторно додати файли , які ви ж хочете додати.


[1] Зауважте (як пояснено в коментарях), це зазвичай трапляється лише тоді, коли РЕПО є абсолютно новим ("первозданним") або якщо жодних комісій не було здійснено. Більш технічно, коли немає каси або робочого дерева.

Просто зробити це більш зрозумілим :)


Так, це більше схоже на видалення самого створеного індексу. Добре, що я не вимагаю повторної ініціалізації git. Дякую!
сарат

Ви впевнені, що це безпечна операція? Я щойно це зробив (насправді перемістив індекс убік) і отримав усі інші файли, які ставились на видалення.
inger

@inger "Якщо у вас незаймане репо". У вас явно цього не було.
sehe

Власне, мені було цікаво, що ти маєш на увазі під "первозданною репо" (мені також не пощастило з Google) .. Тож ти мав на увазі порожнє репо насправді?
inger

1
@inger Згоден. Я повинен був припустити, що в ОП трапилася така точна ситуація - він цього не уточнює, але його опис залишає можливість. У будь-якому випадку, я просто обмінююся інформацією і не можу вплинути на голосування :(. Додав слово попередження до тексту відповіді, якщо це допоможе іншим у майбутньому.
1313

15

Використовуйте git reset HEADдля скидання індексу без вилучення файлів. (Якщо ви хочете скинути лише певний файл у індексі, ви можете git reset HEAD -- /path/to/fileце зробити.)

Оператор трубопроводу в оболонці приймає stdoutпроцес зліва і передає його як stdinпроцесу праворуч. Це по суті еквівалент:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

але замість цього є $ proc1 | proc2, другий процес може почати отримання даних до того, як перший буде зроблений, і не буде задіяний фактичний файл.


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

3
Просто введіть, git reset HEADне вказуючи нічого іншого, і він скине весь індекс. Потім ви можете просто знову додати лише потрібні файли.
Бурштин

Я отримав таку помилку. Я ніколи раніше не вчиняв цих предметів. $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
сарат

1
Спробуйте просто git resetтоді, без цього HEAD.
Бурштин

Я вже намагався, що опинився в наступній помилці. $ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
сарат

9
git stash && git stash pop

2
Я б зробив 'git stash && git stash pop', щоб копія також була видалена. 'Apply' залишить скриньку в списку сховища.
Чітті

8

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

git rm -rf --cached .

знемагати все. Це фактично те саме, що і рішення Sehe, але дозволяє уникнути спілкування з внутрішніми пристроями Git.


це фактично спонукає Git видалити все з кешованої області.
Visionary Software Solutions

1
Кеш також відомий як область постановки, тому я не впевнений, що ви отримуєте.
jjlin

З sehe, rm .git / index дуже небезпечний - обов’язково прочитайте ПРИМІТКА, яку він має про абсолютно новий репо! Це набагато безпечніше для інших 99,999% часу. Я не читав уважно, і мені довелося підірвати свою робочу копію і повторно клонувати після виконання rm .git / index на моїй робочій копії.
phpguru

НЕ використовуйте цю команду! Це змінить ВСІЙ проект на стан, що не відстежується (включаючи ті, які не ставились). Це не рішення вихідного питання. Правильне рішення за допомогою команди 'git rm' полягає в тому, щоб ТОЛЬКО вказати файли, які ви хочете неставити: git rm -rf --cached <файли, які ви хочете відключити>.
Монте Крізор

Ви повинні використовувати цю команду лише тоді, коли у вас є нове репо-повідомлення без жодних комісій (це означає, що "HEAD не встановлено" означає), але ви не хочете просто видувати, .gitтому що ви налаштували іншу конфігурацію репо. хочу зберегти. Я відредагував це, щоб уточнити це.
jjlin

5

Попередження: не використовуйте таку команду, якщо ви не хочете втратити роботу, що не працює!

Використання git resetбуло пояснено, але ви також попросили пояснення конвеєрних команд, так що тут:

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Команда git ls-filesперераховує всі файли, про які знає git. Опція -zнакладає на них певний формат, очікуваний формат xargs -0, який потім посилається rm -fна них, що означає видалити їх, не перевіряючи на підтвердження.

Іншими словами, "перерахуйте всі файли, про які знає git, і видаліть локальну копію".

Потім ми переходимо до цього git diff, що показує зміни між різними версіями елементів, про які знає git. Це можуть бути зміни між різними деревами, відмінності між локальними копіями та віддаленими копіями тощо.
Як тут використовується, він показує нестандартні зміни; файли, які ви змінили, але ще не ввели. Цей параметр --name-onlyозначає, що ви хочете (повні) лише імена файлів і --diff-filter=Dозначає, що вас цікавлять лише видалені файли. (Гей, чи не просто ми видалили купу матеріалів?) Потім це потрапляє у xargs -0ми, що ми бачили раніше, і посилається git rm --cachedна них, це означає, що вони видаляються з кеша, тоді як робоче дерево слід залишити в спокої - за винятком цього Ви щойно видалили всі файли зі свого робочого дерева. Тепер вони також видалені з вашого індексу.

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


TL; DR: ти просто всьому вклав шланг; почати спочатку і використовувати git resetз цього моменту.


2

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

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

git reset --hard

Я кажу "обережно", оскільки git reset --hard знищить невідомі зміни вашої робочої копії та індексу. Однак у цій ситуації це здається так, ніби ви просто хочете повернутися до штату на останньому здійсненні, і неспроможні зміни все одно були втрачені.

Оновлення: звучить з ваших коментарів до відповіді Амбер, що ви ще не створили жодних комітетів (оскільки HEAD неможливо вирішити), тож це не допоможе, боюся.

Щодо роботи цих труб: git ls-files -zі git diff --name-only --diff-filter=D -zобидва виводять список імен файлів, розділених байтом 0. (Це корисно, оскільки, на відміну від нових рядків, 0байти гарантовано не зустрічаються у назви файлів у Unix-подібних системах.) Програма, xargsпо суті, будує командні рядки зі свого стандартного вводу за замовчуванням, беручи рядки зі стандартного введення та додаючи їх до кінця командного рядка. -0Варіант каже очікувати стандартне введення шляху розділених 0байт. xargsможе кілька разів викликати команду, щоб використовувати всі параметри зі стандартного введення, переконуючись, що командний рядок ніколи не стає занадто довгим.

Як простий приклад, якщо у вас є названий файл test.txtіз таким вмістом:

hello
goodbye
hello again

... тоді команда xargs echo whatever < test.txtбуде викликати команду:

echo whatever hello goodbye hello again

Я ніколи не приймав жодних зобов’язань, тому він скаже, що не можу вирішити HEAD. Що ми робимо в таких ситуаціях. Велике спасибі за детальне пояснення труби.
сарат

8
Якщо ви просто змінили свою ігнорувальну функцію git і додали git - все, щоб включити багато файлів, НЕ запускайте скидання git --характер, щоб знезаразити їх. БУДУТЬ ВІДБУДЕНО !!
Радійте

5
Увааах !! Можливо, вам потрібно виділити слово «обережно» . Я щойно побачив ці три слова "git reset --hard", і всі мої нестандартні файли є ... fufff !! пішов !!!!!
Vineeth Chitteti

1

Якщо ви хочете зняти всі зміни, використовуйте команду нижче,

git reset --soft HEAD

У випадку, якщо ви хочете знеструмити зміни та повернути їх із робочого каталогу,

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