Чи можливо переміщувати / перейменувати файли в Git та зберігати їхню історію?


667

Я хотів би перейменовувати / перемістити піддерево проекту в Git, переміщуючи його

/project/xyz

до

/components/xyz

Якщо я використовую звичайну інформацію git mv project components, то вся історія xyz projectфіксування втрачається. Чи є спосіб перемістити це таким чином, щоб історія зберігалася?



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

Про правила, якими керується Git при виявленні перейменування каталогів, дивіться мою відповідь нижче
VonC

Я написав відповідь тут. Сподіваюся, це спрацює. stackoverflow.com/questions/10828267/…
Махмут EFE

Відповіді:


651

Git виявляє перейменування, а не зберігає операцію з фіксацією, тож використовуєте ви git mvчи mvне маєте значення.

logКоманда приймає --followаргумент , який продовжує історію до операції перейменування, тобто, він шукає подібне зміст з допомогою евристики:

http://git-scm.com/docs/git-log

Для пошуку повної історії використовуйте таку команду:

git log --follow ./path/to/file

63
Я підозрюю, що це врахування ефективності. Якщо вам не потрібна повна історія, сканування вмісту вимагатиме більше часу. Найпростіший спосіб - налаштувати псевдонім git config alias.logf "log --follow"і просто написати git logf ./path/to/file.
Тролі Томсен

13
@TroelsThomsen цей електронний лист Лінуса Торвальдса, пов'язаний з цією відповіддю , вказує на те, що це навмисний вибір дизайну Git, оскільки він нібито набагато потужніший, ніж відстеження перейменувань тощо.
Еміль Лундберг,

127
Ця відповідь трохи вводить в оману. Git "виявляє перейменування", але дуже пізно в грі; питання полягає в тому, як ви гарантуєте, що Git доріжки перейменовує, і хтось, читаючи це, може легко зробити висновок про те, що Git автоматично визначає їх для вас і записує це. Це не. У Git немає реального поводження з перейменами, а натомість є інструменти злиття / журналу, які намагаються з’ясувати, що сталося - і рідко отримують це правильно. У Лінуса є помилковий, але жорстокий аргумент щодо того, чому git ніколи не повинен робити це правильним чином і відслідковувати перейменування прямо. Отже, ми тут застрягли.
Кріс Москіні

29
Важливо: якщо ви перейменовуєте каталог, наприклад, під час перейменування пакету Java, обов’язково виконайте два коміти, спочатку для команди 'git mv {old} {new}', а потім для оновлення всіх файлів Java, на які посилається змінений каталог пакунків. Інакше git не може відслідковувати окремі файли навіть із параметром --follow.
nn4l

44
Хоча Лінус, мабуть, робить дуже мало помилок, однак, здається, це одна. Просто перейменування папки спричиняє завантаження масивної дельти в GitHub. Що робить мене обережним щодо перейменування моїх папок ... але це досить велика пряма куртка для програміста. Інколи я маю переосмислити значення чогось або змінити спосіб класифікації. Лінус: "Іншими словами, я маю рацію. Я завжди правий, але іноді я більше правий, ніж в інші часи. І, чорт, коли я кажу, що" файли не мають значення ", я дійсно маю рацію ( тм). " ... У мене є сумніви щодо цього.
Гейб Халсмер

94

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

  • Ви можете переписувати спільну історію, яка є найважливішою НЕ ДОПОМОГА під час використання Git. Якщо хтось ще клонував сховище, ви порушите його, роблячи це. Їм доведеться повторно клонувати, щоб уникнути головних болів. Це може бути нормально, якщо перейменування є досить важливим, але вам потрібно буде це уважно поставитись до уваги.
  • Якщо ви посилалися на файл за допомогою старого імені раніше в історії сховища, ви фактично зламаєте більш ранні версії. Щоб виправити це, вам доведеться зробити трохи більше стрибків з обручем. Це не неможливо, просто нудно і, можливо, не варто.

Тепер, оскільки ти все ще зі мною, ти, мабуть, розробник соло, перейменувавши повністю ізольований файл. Давайте перемістимо файл за допомогою filter-tree!

Припустимо, ви збираєтеся перемістити файл oldу папку dirі дати йому ім’яnew

Це можна зробити git mv old dir/new && git add -u dir/new, але це порушує історію.

Замість цього:

git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD

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

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

Також; Mkdir dir необхідний, лише якщо ви перемістите файл у нову папку, звичайно. , Якщо буде уникати створення цієї папки раніше в історії , ніж існує файл.


57
Як нав’язливий любитель git-log, я б не пішов на це. Файли не були названі тим, що в той момент часу, отже, історія відображає неіснуючу ситуацію. Хто знає, які тести можуть зламатися в минулому! Ризик зламати більш ранні версії - це майже в кожному випадку не варто.
Вінсент

7
@Vincent Ви абсолютно праві, і я намагався бути максимально зрозумілим щодо того, наскільки це рішення є доречним. Я також думаю, що ми говоримо про два значення слова "історія" в цьому випадку, я ціную обоє.
Øystein Steimler

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

3
@ user2291758 - це мій варіант використання. Ці більш потужні команди git небезпечні, але це не означає, що вони не мають дуже вагомих випадків використання, якщо ви знаєте, що ви робите!
Філікс

1
якщо можливо, використання --index-filterдля перейменовування буде набагато швидше, оскільки дерево не доведеться перевіряти та повертати при кожному здійсненні. --index-filterдіє безпосередньо на кожен індекс комісії.
Томас Гайо-Сіоннест

87

Ні.

Коротка відповідь - НІ . Перейменувати файл у Git та запам'ятати історію неможливо. І це біль.

Подейкують, що git log --follow--find-copies-harderце спрацює, але для мене це не працює, навіть якщо зміст файлу є нульовим, і кроки були зроблені git mv.

(Спочатку я використовував Eclipse для перейменування та оновлення пакетів за одну операцію, що, можливо, заплутало Git. Але це дуже поширена річ. --followЗдається, це працює, якщо mvвиконується лише a , а потім a commitі the mvis not too dale.)

Лінус каже, що ви повинні розуміти весь вміст програмного проекту цілісно, ​​не потрібно відстежувати окремі файли. Ну, на жаль, мій маленький мозок цього не може зробити.

Це дійсно прикро, що так багато людей бездумно повторюють твердження, що Git автоматично відстежує ходи. Вони витратили мій час. Гіт такого не робить. За дизайном (!) Git взагалі не відстежує ходи.

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

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

(Є кілька занадто розумних хакків, які повертаються назад і повторюють стару роботу, але вони досить лякають. Див. GitHub-Gist: emiller / git-mv-with-history .)


2
Я вважаю, ти прав. Я просто намагався використовувати php-cs-fixer для переформатування джерела для мого проекту Laravel 5, але він наполягає на зміні великої літери з іменами, щоб відповідати малому значенню папки додатків. Але простори імен (або автозавантаження композитора) працюють лише з CamelCase. Мені потрібно змінити великі літери папки на додаток, але це призводить до втрати моїх змін. Це найбільш тривіальний приклад, але показує, як евристика git не в змозі слідувати навіть найпростішим змінам імен (- нижче і - набрати-копії - складніше, це правило, а не виняток).
Зак Морріс

6
git -1, підрив +1
Cosmin

Це все-таки правда? Це більше причин для мене зараз залишатися з tfs, а збереження історії переміщеного / перейменованого файлу є обов'язковим для великого проекту.
Сезар

@Cesar Якщо під «пам’ятати історію» він означає «слідкувати за перейменами під час перегляду журналу» (що є єдиною корисною справою, про яку ми повинні дбати), то це ніколи не було правдою! Git не "записує" перейменування, але інструменти можуть легко їх виявити та представити нам переймена та переміщення. Якщо "це не працює" для когось, він / вона повинен змінити інструменти, якими він користується. Є безліч чудових графічних інтерфейсів Git, які мають цю здатність.
Мохаммед

Коротка відповідь - так. Поточна версія Git також підтримує "git log - follow". і я згоден з @MohammadDehghan
insng

42
git log --follow [file]

покаже вам історію через перейменування.


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

22
@yoyo: це тому, що git не відстежує перейменування, він їх виявляє. В git mvосновному це робить git rm && git add. Є варіанти, як -M90/ --find-renames=90розглянути файл, який слід перейменовувати, коли він на 90% однаковий.
vdboor

22

Я згоден:

git mv {old} {new}
git add -u {new}

3
Здається, -u не робить для мене нічого, чи припустимо оновити історію?
jeremy

1
Можливо, ви хочете, щоб поведінка -Aнатомість? Знову дивіться тут: git-scm.com/docs/git-add
Джеймс М. Грін

1
Він додає файли, проте він не оновлює історію, так що "ім'я файлу git журналу" показує повну історію. Повна історія відображається лише в тому випадку, якщо ви все ще використовуєте параметр --follow.
Джеремі

3
Я зробив складний рефактор, який перемістив каталог включення (використовуючи mv, не git mv), а потім змінив безліч шляхів #include в межах перейменованих файлів. git не зміг знайти достатню схожість для відстеження історії. Але git add -u - це саме те, що мені було потрібно. статус git тепер вказує на "перейменований", де раніше він показав "видалений" та "новий файл".
Енді Джост

1
Є багато питань щодо ТА, які стосуються мети git add -u. Документи Git, як правило, не допомагають, і це останнє місце, яке я хотів би шукати. Ось одна публікація, яка відображається git add -uв дії: stackoverflow.com/a/2117202 .
nobar

17

Я хотів би перейменовувати / перемістити піддерево проекту в Git, переміщуючи його

/project/xyz

до

/ компоненти / xyz

Якщо я використовую звичайну git mv project components , то вся історія фіксування xyzпроекту втрачається.

Ні (через 8 років, Git 2.19, Q3 2018), оскільки Git виявить перейменування каталогу , і це тепер краще задокументовано.

Див. Комісію b00bf1c , фіксування 1634688 , фіксування 0661e49 , вчинення 4d34dff , фіксування 983f464 , здійснення c840e1a , здійснення 9929430 (27 червня 2018 р.) Та виконання d4e8062 , здійснення 5dacd4a (25 червня 2018 р.) Іллі Ньюреном ( newren) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті 0ce5a69 , 24 липня 2018 р.)

Це тепер пояснено у Documentation/technical/directory-rename-detection.txt:

Приклад:

Коли всі x/a, x/bі x/cперейшли до z/a, z/bі z/c, ймовірно, x/dдодані тим часом також захотіли б перейти z/d, натякаючи, що весь каталог ' x' перемістився в 'z '.

Але це багато інших випадків, таких як:

одна сторона історії перейменовує x -> z, а інша перейменовує якийсь файл у x/e, викликаючи необхідність злиття зробити перехідне перейменування.

Щоб спростити виявлення перейменування каталогу, Git виконує ці правила:

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

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

Ви можете побачити безліч тестів t/t6043-merge-rename-directories.sh, які також вказують на те, що:

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

15

Об'єктивна

  • Використання (натхнене у Smar , запозичене у Exherbo )git am
  • Додати історію фіксації скопійованих / переміщених файлів
  • З одного каталогу в інший
  • Або з одного сховища в інше

Обмеження

  • Теги та гілки не зберігаються
  • Історія скорочується при перейменуванні файлу шляху (перейменування каталогу)

Підсумок

  1. Витягнути історію у форматі електронної пошти за допомогою
    git log --pretty=email -p --reverse --full-index --binary
  2. Реорганізуйте дерево файлів та оновіть назви файлів
  3. Додайте нову історію за допомогою
    cat extracted-history | git am --committer-date-is-author-date

1. Витягнути історію у форматі електронної пошти

Приклад: історія Екстракт file3, file4іfile5

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

Встановити / очистити місце призначення

export historydir=/tmp/mail/dir       # Absolute path
rm -rf "$historydir"    # Caution when cleaning the folder

Витягування історії кожного файлу у форматі електронної пошти

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

На жаль, варіант --followабо --find-copies-harderне може бути поєднаний з--reverse . Ось чому історія вирізається, коли файл перейменовано (або коли батьківський каталог перейменовано).

Тимчасова історія у форматі електронної пошти:

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

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


2. Реорганізуйте дерево файлів та оновіть назви файлів

Припустимо, ви хочете перемістити ці три файли в інший репо-файл (може бути тим же репо).

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # from subdir
│   │   ├── file33    # from file3
│   │   └── file44    # from file4
│   └── dirB2         # new dir
│        └── file5    # from file5
└── dirH
    └── file77

Тому реорганізуйте свої файли:

cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2

Зараз ваша тимчасова історія:

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

Змінюйте також імена файлів в історії:

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

3. Застосовуйте нову історію

Ваше інше репо:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

Застосування комітетів із тимчасових файлів історії:

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date

--committer-date-is-author-dateзберігає оригінальні часові позначки на комісію (коментар Дана Бонахеї ).

Ваше інше репо тепер:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB
│   ├── dirB1
│   │   ├── file33
│   │   └── file44
│   └── dirB2
│        └── file5
└── dirH
    └── file77

Використовуйте git statusдля перегляду кількості комісій, готових до надсилання :-)


Додатковий фокус: Перевірте перейменовані / переміщені файли в межах репо

Щоб перелічити перейменовані файли:

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

Додаткові налаштування: Ви можете виконати команду git logза допомогою параметрів --find-copies-harderабо --reverse. Ви також можете видалити перші два стовпці, скориставшись cut -f3-повним шаблоном '{. * =>. *}' І скопірувавши його.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'

4
ПОПЕРЕДЖЕННЯ: Ця методика розбиває коміти, які змінюють 2 або більше файлів на окремі фрагментовані коміти, і, крім того, розшифровує їх порядок шляхом сортування за назвою файлу (таким чином, фрагменти одного оригінального комітету не виявляються суміжними в лінійній історії). Отже, історія, що виходить, є "коректною" лише окремо для кожного файлу. Якщо ви переміщуєте більше одного файлу, НІКОЛЬНИЙ з нових комісій у отриманій історії представляє собою послідовний знімок переміщених файлів, які коли-небудь існували в історії початкового репо.
Дан Бонахея

2
Привіт @DanBonachea Дякуємо за ваш цікавий відгук. Я успішно перемістив деякі репозиції, що містять кілька файлів, використовуючи цю техніку (навіть із перейменованими файлами та файлами, переміщеними в каталогах). Що ви пропонуєте змінити у цій відповіді. Як ви вважаєте, ми повинні додати банер ПОПЕРЕДЖЕННЯ у верхній частині цієї відповіді, що пояснює обмеження цієї методики? Ура
олибре

2
Я адаптував цю методику, щоб уникнути проблеми, перевернувши петлі команди генерації журналу git на кроці 1. Тобто а не запускати журнал git один раз на файл, запускайте його рівно один раз зі списком файлів у командному рядку та генеруйте єдиний єдиний журнал. Таким чином коміти, які змінюють 2 або більше файлів, залишаються єдиним фіксатором у результаті, а всі нові комітети підтримують свій початковий відносний порядок. Зауважте, що це також потребує змін на кроці 2 при перезаписі імен файлів у (тепер уніфікований) журнал. Я також використовував git am - committer-date-is-author-date, щоб зберегти початкові часові позначки фіксації.
Дан Бонахея

1
Дякую за експерименти та обмін. Я трохи оновив відповідь для інших читачів. Однак мені знадобився час, щоб перевірити вашу обробку. Будь ласка, відредагуйте цю відповідь, якщо ви хочете навести приклади командних рядків. Ура;)
олібре

4

Я дотримувався цього багатоетапного процесу для переміщення коду до батьківського каталогу та збереженої історії.

Крок 0: Створено філію "Історія" з "master" для зберігання

Крок 1: Використовували інструмент git-filter-repo для переписування історії. Ця команда нижче перемістила папку "FolderwithContentOfInterest" на один рівень вгору та змінила відповідну історію фіксації

git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force

Крок 2: На цей час сховище GitHub втратило шлях віддаленого сховища. Додана віддалена довідка

git remote add origin git@github.com:MyCompany/MyRepo.git

Крок 3. Витягніть інформацію на сховище

git pull

Крок 4: З'єднайте локальну втрачену гілку з початковою гілкою

git branch --set-upstream-to=origin/history history

Крок 5: Якщо буде запропоновано, конфлікт злиття адреси для структури папки

Крок 6: Натисніть !!

git push

Примітка: Модифікована історія та переміщена папка, здається, уже скоєні. enter code here

Зроблено. Код переміщується до батьківського / потрібного каталогу, зберігаючи історію недоторканою!


2

Хоча ядро ​​Git, сантехніка Git не відслідковує перейменування, історія, яку ви показуєте в журналі Git "порцеляна", може виявити їх, якщо вам подобається.

Для заданої можливості git logскористайтесь опцією -M:

git log -p -М

З поточною версією Git.

Це працює і для інших команд, як git diff.

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

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

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

git config diff.renames 1

Файли , що переміщаються з однієї директорії в іншу буде виявлений. Ось приклад:

commit c3ee8dfb01e357eba1ab18003be1490a46325992
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:20:19 2017 -0500

    test rename again

diff --git a/yyy/power.py b/zzz/power.py
similarity index 100%
rename from yyy/power.py
rename to zzz/power.py

commit ae181377154eca800832087500c258a20c95d1c3
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:19:17 2017 -0500

    rename test

diff --git a/power.py b/yyy/power.py
similarity index 100%
rename from power.py
rename to yyy/power.py

Зауважте, що це працює завжди, коли ви використовуєте розл., А не лише з git log. Наприклад:

$ git diff HEAD c3ee8df
diff --git a/power.py b/zzz/power.py
similarity index 100%
rename from power.py
rename to zzz/power.py

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

 $ git merge -v master
 Auto-merging single
 Merge made by the 'recursive' strategy.
  one => single | 4 ++++
  1 file changed, 4 insertions(+)
  rename one => single (67%)

Результатом цього стала робоча директорія з перейменованим файлом та внесені обидва текстові зміни. Таким чином, Git може зробити правильно, незважаючи на те, що він чітко не відстежує перейменування.

Це пізня відповідь на старе запитання, тому інші відповіді, можливо, були правильними для версії Git на той час.


1

Спочатку створіть окремий комітет із лише перейменуванням.

Тоді будь-які можливі зміни вмісту файлу ставлять в окремий комітет.


1

Щоб перейменувати каталог або файл (я не знаю багато про складні випадки, тому можуть бути деякі застереження):

git filter-repo --path-rename OLD_NAME:NEW_NAME

Щоб перейменувати каталог у файлах, які згадують його (можна використовувати зворотні дзвінки, але я не знаю як):

git filter-repo --replace-text expressions.txt

expressions.txtце файл, заповнений на зразок рядків literal:OLD_NAME==>NEW_NAME(можна використовувати RE Python з RE regex:або glob зglob: ).

Щоб перейменувати каталог у повідомленнях комітів:

git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'

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

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

Якщо ви не хочете зберігати рефлекси (вони будуть відображатися в історії філії Git GUI), вам доведеться додати --replace-refs delete-no-add.


0

Просто перемістіть файл і спробуйте за допомогою:

git add .

Перш ніж скористатися, ви можете перевірити стан

git status

Це покаже:

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    old-folder/file.txt -> new-folder/file.txt

Я тестував версію Git 2.26.1.

Витягнуто з довідкової сторінки GitHub .


-3

Я роблю переміщення файлів, а потім роблю

git add -A

який помістив у зону штампування всі видалені / нові файли. Тут git розуміє, що файл переміщено.

git commit -m "my message"
git push

Я не знаю чому, але це працює для мене.


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