Ответ 1
На самом деле вы можете иметь несколько разных промежуточных областей (в буквальном смысле, несколько индексных файлов) в git. Чтобы достичь желаемого эффекта, вам все равно придется написать свой собственный вариант git add -p
, поэтому я буду делать набросок, как бы это сделать.
Индексный файл по умолчанию - тот, который использует git, если вы не указываете его в какой-либо другой индексный файл - находится в .git/index
(или, более корректно в оболочке, $GIT_DIR/.index
где $GIT_DIR
взят из среды или если не установлен там, из git rev-parse --git-dir
).
Однако если вы установите переменную среды GIT_INDEX_FILE
, git будет использовать этот файл вместо индекса. Таким образом, вы можете начать процесс "разброса изменений на четыре ветки", выполнив что-то вроде этого:
GIT_DIR=${GIT_DIR:-$(git rev-parse --git-dir)} || exit 1
index_tmp_dir=$(mktemp -d) || exit 1
trap "rm -rf $index_tmp_dir" 0 1 2 3 15 # clean up on exit
# make four copies of initial staging area
for f in i1 i2 i3 i4; do
cp $GIT_DIR/index $index_tmp_dir/$f
done
# THIS IS THE HARD PART:
# Now, using 'git diff-files -p' or similar, get patches
# (diff hunks).
# Whenever you're ready to stage one, pick an index for it,
# then use:
GIT_INDEX_FILE=$index_tmp_dir/$which git apply --cached < diffhunk
# Once done, commit each index file separately with some
# variation on:
for f in i1 i2 i3 i4; do
GIT_INDEX_FILE=$index_tmp_dir/$which git commit
done
Для части с надписью "трудная часть" лучше всего скопировать perl-скрипт git add-interactive, находящийся в $(git --exec-path)/git-add--interactive
, а затем изменить его так, чтобы он подходил, Чтобы снять ограничение "ровно четыре коммита", сделайте так, чтобы это измененное интерактивное добавление динамически создавало новый индексный файл (путем копирования оригинала или, возможно, создания "пустого" индекса, равного HEAD
или как угодно; см. git read-tree
как Что ж).
Редактировать: некоторые изменения в разделе действительно должны почти наверняка использовать git write-tree
и git commit-tree
для создания новых веток из каждого из этих коммитов, используя родителя текущего коммита в качестве родителя, вместо того, чтобы разрешить git commit
для строки фиксирует вместе как линейную цепь. Это означает, что нужно также выбрать некоторую схему именования для этих различных вновь созданных ветвей.