Как подготовить только часть нового файла с помощью git?

222

Я люблю мерзавца добавить - интерактивно . Теперь это часть моего ежедневного рабочего процесса.

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

Например, с помощью git add -i я могу выбрать опцию patch и даже отредактировать отдельные фрагменты, чтобы разместить части нового кода, оставив комментарии кода отладки без изменений. Мне нравится работать таким образом, потому что становится очевидным, над какими местами мега-патча, над которым я сейчас работаю, все еще нужно работать.

К сожалению, я не могу сделать то же самое с неотслеживаемым файлом. Либо я ставлю весь файл, либо ничего. Обходной путь, который я использовал, - это подготовка или даже фиксация нового файла, когда он пуст, а затем подготовка отдельных изменений обычным способом. Но это решение похоже на грязный взлом, и когда я забываю или передумал, оно создает больше проблем, чем должно быть.

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

Augustin
источник

Ответы:

415

Вау, все это update-indexи hash-objectбизнес кажутся слишком сложными. Как насчет этого вместо этого:

git add -N new_file
git add -i

От git help add:

-N, --intent-to-add
    Record only the fact that the path will be added later.  An entry
    for the path is placed in the index with no content.  This is useful
    for, among other things, showing the unstaged content of such files
    with git diff and committing them with git commit -a.
Ричард Хансен
источник
9
++ 1! должный кредит. Я слишком доверяю тому, что уже знаю эти страницы…</shame>
sehe
1
Хорошо найдено. Я должен был прокрутить страницу справочника немного дальше. Возможно, я должен вернуть значок Git Pro.
dave1010
3
Вам интересно, почему git-gui не использует это внутренне, чтобы иметь возможность выделять строки из нового файла?
Дейвин
6
Замечательное -Nоткрытие, спасибо! Хотя я бы предпочел объединить это -pв таком случае. gid add -N the_file& git add -p. Следует добавить, что -Nтакже работает с-A
Кирилл CHAPON
@Deiwin - вы можете добавить [guitool] в ваш .gitconfig для выполнения «git add -N $ FILENAME»: [guitool «Добавить с намерением»] cmd = «git add -N $ FILENAME» needsfile = yes noconsole = yes
Стив Фолли
7

Самый простой способ сделать это (и imho интерактивная постановка в целом) это git gui. Он поставляется в комплекте с git и должен работать практически на всех платформах, которые поддерживаются git.

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

Скриншот Git Gui

Chronial
источник
Это творческий ответ, а иногда очень и очень полезный.
Пабло Олмос де Агилера С.
3
Просто обратите внимание, что не все git-дистрибутивы включают git gui. Например, в Debian он находится в отдельном пакете, называемом «git-gui».
Кристопер
Долгие годы искали (не достаточно сильно) эту функцию, это
меняет
2
Для меня подготовка отдельных строк неотслеживаемых файлов git guiникогда не работала. На самом деле, это отключает эти пункты меню .
Дейвин
2
@ Deiwin Я, наверное, пропустил это в вопросе - мой скриншот показывает уже отслеженный файл. Если вы хотите использовать git guiдля нового файла, вы должны git add -N new_fileсначала запустить - см. Ответ Ричарда Хансена.
Хрони
6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

Простая демонстрация:

mkdir /tmp/demo
cd /tmp/demo
git init .

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Подсказка Если вы уверены, что «пустой» большой двоичный объект уже существует в вашей базе данных объектов git, вы можете e69de29bb2d1d6434b8b29ae775ad8c2e48c5391вместо этого жестко закодировать хеш . Я не рекомендую делать это
  • Подсказка Если вы работаете в Windows, вы можете просто использовать NUL:вместо /dev/null. В противном случае используйте что-то вродеecho -n '' | git hash-object --stdin -w

Теперь индекс будет содержать newfileпустой BLOB-объект, а пустой BLOB-объект будет введен в базу данных объектов, если он еще не существовал:

$ find .git/objects/ -type f 
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   newfile
#

$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

Это должно быть именно то, что вы хотите. Могу ли я также порекомендовать подключаемый модуль vim fugitive для очень интеллектуального управления индексами (см. Better git add -p? )

sehe
источник
1
Кажется, это хорошо работает. Я связал это с "stage-empty-file", так как это немного сложно запомнить.
dave1010
@ dave1010: рад, что это помогло! Да, я думал о добавлении псевдонима, но я не знал, как вы будете обрабатывать, например, шаблоны или несколько аргументов имени файла в целом. Поэтому я решил не
сехе
2

Изменить: это, кажется, не работает сейчас. Я уверен, что это было раньше (на git 1.7.1). В случае, если это не сработает, я предлагаю постановку, /dev/nullкак показано выше:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

Если вы используете Windows (без /dev/null), вы можете заменить ее на путь к пустому файлу.

Оригинальный ответ

Вы хотите

git add -p # (or --patch)

Это добавляет неотслеживаемые файлы для меня. Со страницы руководства:

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

Это эффективно запускает add --interactive, но обходит начальное командное меню и напрямую переходит к подкоманде patch. Подробнее см. «Интерактивный режим».

dave1010
источник
2
Как бы это ни было интересно, это не работает для меня (git 1.7.4); git add -p newfileне работает вообще (ню-эффект) и эффект git add --interactive'[a] dd unracked' имеет эффект git add newfile; Редактировать также проверено с помощью git 1.7.5.3; нет кости
сехе
Хорошая подсказка для Windows, добавлены подсказки для этого в моем ответе. Thx
Сехе
-2

Просто для записи другой возможности: я использую

git add -N file
git add -p file

И тогда вы можете ставить куски или редактировать их на месте.

Педро Адам Вергара
источник
1
Этот ответ говорит так же, как принятый ответ, который датируется 2011 годом. Downvote.
Станислав Панкевич
Принятый ответ сочетается add -Nс add -i. Я просто добавил, что add -pвместо add -iработ тоже.
Педро Адам Вергара