Як створити нову (і порожню!) Гілку кореня?


135

Я хотів би визначити нову гілку "root" у цьому сховищі git. Під «кореневою» гілкою я маю на увазі гілку, повністю незалежну від усіх інших гілок у сховищі 1 .

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

Це означає, що навіть якби я дав Aнову гілку <start-point>, ця нова гілка не починалася б з "чистого аркуша", а скоріше містила б усі файли, які були зроблені в A.

Чи є якимось чином я можу створити цілком оголену гілку в цьому сховищі, <start-point>якомога ближче A?


1 BTW, це не еквівалентно створенню нового репо. Окремі репости були б менш зручними з багатьох причин.


EDIT : Гаразд, це я і зробив, грунтуючись на відповіді vcsjones :

# save rev of the current earliest commit
OLDBASE=$(git rev-list --max-parents=0 HEAD)

# create a new orphan branch and switch to it
git checkout --orphan newbranch
# make sure it's empty
git rm -rf .

# create a new empty commit in the new branch, and
# save its rev in NEWBASE
git commit --allow-empty -m 'base commit (empty)'
NEWBASE=$(git rev-list HEAD)

# specify $NEWBASE as the new parent for $OLDBASE, and
# run filter-branch on the original branch
echo "$OLDBASE $NEWBASE" > .git/info/grafts
git checkout master
git filter-branch

# NOTE: this assumes that the original repo had only one
# branch; if not, a git-filter-branch -f <branch> command
# need to be run for each additional branch.

rm .git/info/grafts

Незважаючи на те, що ця процедура дещо задіяна, кінцевим результатом є пуста база, яка може послужити <start-point>для будь-якої нової "чистої шиферної гілки"; все, що мені тоді потрібно зробити, - це

git checkout -b cleanslate $(git rev-list --max-parents=0 HEAD)

В майбутньому я завжди буду створювати такі сховища:

git init
git commit --allow-empty -m 'base commit (empty)'

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



1
@Anonymousmoose: Просто для запису (а не для дискусій): я не згоден з вашою думкою.
kjo

1
Там , здається, набагато більш просте рішення на основі git rebase --onto, див stackoverflow.com/questions/645450 / ...
Стефан Горічон

Відповіді:


223

Використовуйте під --orphanчас створення філії:

git checkout --orphan YourBranchName

Це створить нову гілку з нульовою комісією, однак усі ваші файли будуть інсценовані. У цей момент ви могли просто їх видалити.
("видалити їх": A git reset --hardспорожнить індекс, залишивши вас порожнім робочим деревом)

Подивіться на сторінку чоловіка для оформлення замовлення для отримання додаткової інформації про --orphan.


Це по суті створює порожній шифер? Як, з нуля? Або це зберігає всі ваші попередні зміни, але просто не в історії git?
Con Antonakos

4
@ConAntonakos Це створює нову гілку без батьків. На інші гілки це не впливає, всі їх зміни зберігаються.
fuz

11

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

$ git checkout --orphan dev2
Switched to a new branch 'dev2'
$ git reset # unstage all the files, you probably don't want to commit all of them
$ git commit --allow-empty -m 'Initial empty commit'
[dev2 (root-commit) a515c28] Initial empty commit

1
Я вважаю, що це не потрібно з 2012 року, оскільки ви можете перезавантажити корінь .
Timmmm


1

Чи є якимось чином я можу створити цілком оголену гілку в цьому сховищі.

Фактична команда для використання (з Git 2.28+):

git switch --discard-changes --orphan newBranch
# or
git switch -f --orphan newBranch

git switchдоступний з Git 2.23 (серпень 2019) і замінює стару заплутану git checkoutкоманду .

Але я б рекомендував Git 2,28 (Q3 2020), тому що git switch --discard-changes --orphan він був оптимізований у цій версії.

Див. Комісію 8d3e33d , фіксування 8186128 (21 травня 2020 р.) Від Брайана m. Карлсон ( bk2204) .
(Об’єднав Хуніо С Хамано - gitster- у віддаленні4444 , 09 червня 2020 р.)

builtin/checkout: спростити ініціалізацію метаданих

Підписано: Брайан м. Карлсон
Відгук: Деррік Столі

Коли ми викликаємо init_checkout_metadataвreset_tree, ми хочемо передати ідентифікатор об'єкта фіксації в питанні , так що вона не може бути передана на фільтри, або , якщо немає фіксації, дерева.

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

Єдиний випадок, коли у нас немає об’єкта фіксації - це при посиланні git switchна--orphan .

Більше того, ми можемо потрапити лише на цей шлях коду без об'єкта фіксації додатково або з --forceабо--discard-changes .

У такому випадку немає сенсу ініціалізувати метадані замовлення на комітку чи дерево, оскільки

  • (а) немає комітів, лише порожнє дерево, і
  • (b) ми ніколи не будемо використовувати дані, оскільки жоден файл не буде розмитий при перевірці гілки без файлів.

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

Тест:

git switch master
echo foo >foo.txt
git switch --discard-changes --orphan new-orphan2
git ls-files >tracked-files
# test_must_be_empty tracked-files
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.