Сделать текущий коммит единственным (начальным) коммитом в Git-репозитории? - PullRequest
607 голосов
/ 13 марта 2012

В настоящее время у меня есть локальный репозиторий Git, который я отправляю в репозиторий Github.

Локальный репозиторий имеет ~ 10 коммитов, а репозиторий Github является синхронизированным дубликатом этого.

Что я хотел бы сделать, это удалить ВСЕ историю версий из локального репозитория Git, чтобы текущее содержимое репозитория отображалось как единственная фиксация (и, следовательно, более старые версии файлов в репозитории не сохраняются).

Тогда я бы хотел перенести эти изменения в Github.

Я исследовал Git ReBase, но это больше подходит для удаления определенных версий. Другим потенциальным решением является удаление локального репо и создание нового - хотя это, вероятно, создаст много работы!

ETA: есть определенные каталоги / файлы, которые не отслеживаются, - если возможно, я хотел бы сохранить отслеживание этих файлов.

Ответы [ 14 ]

930 голосов
/ 13 марта 2012

Вот подход грубой силы.Также удаляется конфигурация репозитория.

Примечание : Это НЕ работает, если в репозитории есть подмодули!Если вы используете субмодули, вы должны использовать, например, интерактивное перебазирование

Шаг 1: удалить всю историю ( Убедитесь, что у вас есть резервная копия, это не может быть восстановлено )

cat .git/config  # note <github-uri>
rm -rf .git

Шаг 2: восстановить репозиторий Git только с текущим контентом

git init
git add .
git commit -m "Initial commit"

Шаг 3: перейти на GitHub.

git remote add origin <github-uri>
git push -u --force origin master
536 голосов
/ 27 октября 2012

Единственное решение, которое работает для меня (и поддерживает работу подмодулей) -

git checkout --orphan newBranch
git add -A  # Add all files and commit them
git commit
git branch -D master  # Deletes the master branch
git branch -m master  # Rename the current branch to master
git push -f origin master  # Force push master branch to github
git gc --aggressive --prune=all     # remove the old files

Удаление .git/ всегда вызывает огромные проблемы, когда у меня есть подмодули. Использование git rebase --root может как-то вызвать у меня конфликты (и займет много времени, так как у меня было много истории).

87 голосов
/ 22 марта 2013

Это мой любимый подход:

git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})

Это создаст новую ветку с одним коммитом, который добавляет все в HEAD. Больше ничего не меняет, поэтому совершенно безопасно.

31 голосов
/ 15 марта 2012

Другой вариант, который может оказаться трудоемким, если у вас много коммитов, это интерактивная перебазировка (при условии, что ваша версия git> = 1.7.12): git rebase --root -i

Когда в вашем редакторе представлен список коммитов:

  • Измените «pick» на «reword» для первого коммита
  • Измените «pick» на «fixup» для каждого другого коммита

Сохранить и закрыть.Git начнет перебазировать.

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

Преимущество заключается в том, что вам не нужно удалять свой репозиторий, и еслиу вас возникли мысли, что у вас всегда есть запасной вариант.

Если вы действительно хотите уничтожить свою историю, сбросьте мастер до этого коммита и удалите все остальные ветви.

18 голосов
/ 19 апреля 2014

Вариант Ларсмана Предложенный метод:

Сохраните список файлов без отслеживания:

git ls-files --others --exclude-standard > /tmp/my_untracked_files

Сохраните вашу конфигурацию git:

mv .git/config /tmp/

Затем выполните первые шаги Ларсмана:

rm -rf .git
git init
git add .

Восстановление конфигурации:

mv /tmp/config .git/

Отследить неотслеживаемые файлы:

cat /tmp/my_untracked_files | xargs -0 git rm --cached

Затем коммит:

git commit -m "Initial commit"

И, наконец, нажмите на ваш репозиторий:

git push -u --force origin master
5 голосов
/ 04 апреля 2016

Вы можете использовать мелкие клоны (git> 1.9):

git clone --depth depth remote-url

Дальнейшее чтение: http://blogs.atlassian.com/2014/05/handle-big-repositories-git/

4 голосов
/ 05 апреля 2014

git filter-branch является инструментом основной хирургии.

git filter-branch --parent-filter true -- @^!

--parent-filter получает родителей на стандартный ввод и печатает переписанных родителей на стандартный вывод; unix true успешно завершает работу и ничего не печатает, поэтому: нет родителей. @^! - это Git сокращение для"главный коммит, но не любой из его родителей". Затем удалите все другие ссылки и нажмите на досуге.

2 голосов
/ 12 февраля 2019

Ниже приведен скрипт, адаптированный из ответа @Zeelot.Он должен удалить историю из всех ветвей, а не только из основной ветки:

for BR in $(git branch); do   
  git checkout $BR
  git checkout --orphan ${BR}_temp
  git commit -m "Initial commit"
  git branch -D $BR
  git branch -m $BR
done;
git gc --aggressive --prune=all

Это сработало для моих целей (я не использую подмодули).

2 голосов
/ 06 февраля 2013

Метод, приведенный ниже, является точно воспроизводимым, поэтому нет необходимости запускать клонирование снова, если обе стороны были согласованы, просто запустите сценарий также на другой стороне.

git log -n1 --format=%H >.git/info/grafts
git filter-branch -f
rm .git/info/grafts

Если вы хотите очистить егопопробуйте этот скрипт:

http://sam.nipl.net/b/git-gc-all-ferocious

Я написал скрипт, который "убивает историю" для каждой ветви в хранилище:

http://sam.nipl.net/b/git-kill-history

см. Также: http://sam.nipl.net/b/confirm

0 голосов
/ 31 декабря 2018

Просто удалите репозиторий Github и создайте новый.Безусловно, самый быстрый, самый простой и безопасный подход.В конце концов, что вам нужно, выполняя все эти команды в принятом решении, когда все, что вам нужно, - это основная ветка с одним коммитом?

...