Вставить коммит перед корневым коммитом в Git? - PullRequest
197 голосов
/ 14 марта 2009

Я уже спрашивал о том, как раздавить первые два коммита в репозитории git.

Хотя решения довольно интересные и не настолько изнурительные, как некоторые другие вещи в git, они все еще являются частью мешающего всем, если вам нужно повторять эту процедуру много раз по мере развития вашего проекта ,

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

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

Тогда у меня возникает вопрос, имея существующее хранилище, как мне вставить новый пустой коммит перед первым и переместить всех остальных вперед?

Ответы [ 14 ]

1 голос
/ 07 мая 2015

Вот мой bash скрипт, основанный на ответе Кента с улучшениями:

  • проверяет исходную ветвь, а не только master, когда сделано;
  • Я пытался избежать временной ветки, но git checkout --orphan работает только с веткой, а не с состоянием отсоединенной головы, поэтому он извлекается достаточно долго, чтобы сделать новый корневой коммит, а затем удаляется;
  • он использует хеш нового корневого коммита во время filter-branch (Кент оставил там заполнитель для замены вручную);
  • операция filter-branch перезаписывает только локальные ветви, а не удаленные тоже
  • метаданные автора и коммиттера стандартизированы, так что корневой коммит одинаков для всех репозиториев.

#!/bin/bash

# Save the current branch so we can check it out again later
INITIAL_BRANCH=`git symbolic-ref --short HEAD`
TEMP_BRANCH='newroot'

# Create a new temporary branch at a new root, and remove everything from the tree
git checkout --orphan "$TEMP_BRANCH"
git rm -rf .

# Commit this empty state with generic metadata that will not change - this should result in the same commit hash every time
export GIT_AUTHOR_NAME='nobody'
export GIT_AUTHOR_EMAIL='nobody@example.org'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'
export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
git commit --allow-empty -m 'empty root'
NEWROOT=`git rev-parse HEAD`

# Check out the commit we just made and delete the temporary branch
git checkout --detach "$NEWROOT"
git branch -D "$TEMP_BRANCH"

# Rewrite all the local branches to insert the new root commit, delete the 
# original/* branches left behind, and check out the rewritten initial branch
git filter-branch --parent-filter "sed \"s/^\$/-p $NEWROOT/\"" --tag-name-filter cat -- --branches
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git checkout "$INITIAL_BRANCH"
0 голосов
/ 18 февраля 2013

После ответа Аристотель Пагальцис и другие, но с использованием более простых команд

zsh% git checkout --orphan empty     
Switched to a new branch 'empty'
zsh% git rm --cached -r .
zsh% git clean -fdx
zsh% git commit --allow-empty -m 'initial empty commit'
[empty (root-commit) 64ea894] initial empty commit
zsh% git checkout master
Switched to branch 'master'
zsh% git rebase empty
First, rewinding head to replay your work on top of it...
zsh% git branch -d empty 
Deleted branch empty (was 64ea894).

Обратите внимание, что в вашем репо не должно быть локальных изменений, ожидающих принятия.
Я думаю, git checkout --orphan будет работать на новых версиях git.
Обратите внимание, что большую часть времени git status дает полезные советы.

0 голосов
/ 27 июня 2011

Я знаю, что этот пост старый, но эта страница первая, когда Googling "вставляет коммит git".

Зачем делать простые вещи сложными?

У вас есть A-B-C, и вы хотите A-B-Z-C.

  1. git rebase -i trunk (или что-нибудь до B)
  2. изменить выбор для редактирования в строке B
  3. внести изменения: git add ..
  4. git commit (git commit --amend, который будет редактировать B, а не создавать Z) * ​​1018 *

[Вы можете сделать столько git commit, сколько хотите, чтобы вставить больше коммитов. Конечно, у вас могут возникнуть проблемы с шагом 5, но разрешение конфликта слияния с помощью git - это навык, который вам нужно иметь. Если нет, тренируйтесь!]

  1. git rebase --continue

Просто, не правда ли?

Если вы понимаете git rebase, добавление «корневого» коммита не должно быть проблемой.

Веселись с мерзавцем!

0 голосов
/ 14 марта 2009

Запустить новый репозиторий.

Установите дату обратно на желаемую дату начала.

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

Когда вы доберетесь до сегодняшнего дня, поменяйте местами репозитории, и все готово.

Если вы просто сумасшедший (устоявшийся), но достаточно умный (вероятно, потому, что вам нужно определенное количество умов, чтобы придумывать сумасшедшие идеи, подобные этой), вы будете писать сценарий процесса.

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

...