Зафиксировать только часть файла в Git

2513

Когда я вношу изменения в файл в Git, как я могу выполнить только некоторые из изменений?

Например, как я могу выполнить только 15 строк из 30 строк, которые были изменены в файле?

  • 2
    related stackoverflow.com/q/34609924/52074 : если вам нужно разбить кусок на более мелкие фрагменты.
Теги:
git-commit

22 ответа

3306
Лучший ответ

Вы можете использовать git add --patch <filename> (или -p для краткости), и git начнет разбивать ваш файл на то, что он считает разумными "порциями" (частями файла). Затем он подскажет вам этот вопрос:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Вот описание каждой опции:

  • y подготовить этот кусок для следующего коммита
  • n не ставить этот кусок для следующего коммита
  • q выход; не ставьте этот кусок или любой из оставшихся кусков
  • a ставит этот кусок и все последующие фрагменты в файле
  • d не ставить этот блок или какой-либо более поздний фрагмент в файле
  • g выберите кусок, чтобы перейти к
  • / поиск блока, соответствующего заданному регулярному выражению
  • j оставь этот кусок нерешенным, смотри следующий нерешенный кусок
  • J оставь этот кусок нерешенным, смотри следующий кусок
  • k оставить этот кусок нерешенным, см. Предыдущий нерешенный кусок
  • K оставь этот кусок нерешенным, смотри предыдущий кусок
  • s разделить текущий кусок на более мелкие фрагменты
  • e вручную редактировать текущий блок
  • ? справка по распечатке

Если файл еще не находится в хранилище, вы можете сначала сделать git add -N <filename>. После этого вы можете продолжить с помощью git add -p <filename>.

После этого вы можете использовать:

  • git diff --staged чтобы убедиться, что вы поставили правильные изменения
  • git reset -p чтобы расстегнуть ошибочно добавленные фрагменты
  • git commit -v для просмотра вашего коммита во время редактирования сообщения коммита.

Обратите внимание, что это сильно отличается от команды git format-patch, целью которой является анализ данных .patch файлах .patch.

Ссылка на будущее: Git Tools - Интерактивная постановка

  • 61
    Возможно, было бы полезно отметить, что -p/--patch - это ярлык для действия исправления внутри -i/--interactive команды -i/--interactive которая запускает полезный интерактивный режим .
  • 0
    Что произойдет, если этот файл уже подготовлен?
Показать ещё 11 комментариев
212

Вы можете использовать git add --interactive или git add -p <file>, а затем git commit ( не git commit -a); см. интерактивный режим в git-add manpage или просто следуйте инструкциям.

Современный Git также имеет git commit --interactivegit commit --patch, который является ярлыком для параметра патча в интерактивной фиксации).

Если вы предпочитаете делать это из графического интерфейса, вы можете использовать git-gui. Вы можете просто отметить куски, которые вы хотите включить в фиксацию. Мне лично легче, чем использовать git add -i. Другие Git GUI, такие как QGit или GitX, также могут иметь эту функциональность.

  • 1
    Интересно, что на windows.github.com была поддержка частичной фиксации файлов, но, похоже, она недавно была удалена.
  • 1
    @Juri Я думаю, что поддержка частичной фиксации файлов вернулась.
Показать ещё 3 комментария
113

git gui предоставляет эту функциональность под видом diff. Просто щелкните правой кнопкой мыши интересующую вас линию, и вы увидите пункт меню "Эта строка для фиксации".

  • 7
    для сложных патчей это обычно самый быстрый подход для меня.
  • 3
    Это очень эффективный и интуитивно понятный способ добавления изменений в область подготовки с мелкой детализацией. Также можно выбрать несколько строк и все изменения в этом выборе будут добавлены.
61

Я считаю, что git add -e myfile - самый простой способ (по крайней мере, мое предпочтение), поскольку он просто открывает текстовый редактор и позволяет вам выбрать, какую строку вы хотите выполнить, а какая строка у вас нет. Что касается команд редактирования:

добавленный контент:

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

удаленный контент:

Удаленное содержимое представлено строками, начинающимися с "-". Вы можете предотвратить их удаление путем преобразования "-" в "" (пробел).

измененное содержимое:

Измененное содержимое представлено линиями "-" (удаление старого содержимого), за которым следуют строки "+" (добавление замещающего содержимого). Вы можете предотвратить установку модификации путем преобразования строк "-" в "" и удаления "+",            линий. Помните, что изменение только половины пары, скорее всего, приведет к запутывающим изменениям индекса.

Каждая информация о git add доступна на git --help add

  • 7
    Это было бы более полезно, если бы где-то было четкое объяснение того, как на самом деле выбрать эти строки (то есть фактические команды для ввода). Я не мог найти один в документации. Не могли бы вы добавить ссылку?
  • 3
    Для тех, кому не нравятся сокращенные варианты, -e это --edit .
Показать ещё 4 комментария
42

Если вы используете vim, вы можете попробовать отличный плагин под названием fugitive.

Вы можете увидеть diff файла между рабочей копией и индексом с помощью :Gdiff, а затем добавить строки или столбцы в индекс, используя классические команды vim diff, такие как dp. Сохраните изменения в индексе и скопируйте с помощью :Gcommit, и все готово.

Очень хорошие вступительные видеоролики здесь (см. часть 2).

  • 0
    Большое вам спасибо за эти ссылки. Точно так же, как мне нужно. В частности :diffget/:diffput в визуальном режиме, где я могу выбрать определенные строки, которые я хочу сбросить / зафиксировать. Итак, убедитесь еще раз: vim потрясающий.
30

Я настоятельно рекомендую использовать SourceTree от Atlassian. (Это бесплатно.) Это делает это тривиальным. Вы можете быстро и легко создавать отдельные куски кода или отдельные строки кода.

Изображение 7492

  • 1
    Я согласен, что SourceTree - хороший инструмент для этой цели, потому что он дает вам более детальный контроль, чем это возможно через командную строку.
  • 15
    @cupcake Я бы сказал, что наоборот, поскольку SourceTree, вероятно, использует эти исполняемые файлы git для командной строки, по своей сути всегда можно будет выполнять те же (или более) детальные действия через «командную строку».
Показать ещё 6 комментариев
21

Стоит отметить, что для использования git add --patch для нового файла вам нужно сначала добавить файл в индекс с помощью git add --intent-to-add:

git add -N file
git add -p file
19

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

Вот так:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

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

12

Если вы используете emacs, посмотрите Magit, который предоставляет интерфейс git для emacs. Он хорошо поддерживает промежуточных фрагментов (части файлов).

  • 0
    Я часто путаюсь с командой git, желающей открыть редактор, когда запускаю его из окна оболочки Mx. Перехватывает ли magit это безумие и открывает для этого только новый буфер? (пожалуйста, никаких подсказок background-emacs-daemon; все равно спасибо, но жизнь слишком коротка).
  • 0
    Нет, насколько я могу судить, это не перехватывает это. Но не просто поверьте мне на слово, потому что (1) я почти не использую окно оболочки в Emacs, и (2) я обычно использую emacsclient. Сказав это, если emacsclient является опцией для вас, это, по крайней мере, предотвратило открытие дополнительного окна с emacs и открытием буфера "COMMIT_EDITMSG" в моем существующем окне Emacs.
8

Как и в случае с jdsumsion, вы также можете спрятать свою текущую работу, но затем используйте difffool, например meld, чтобы вытащить выбранные изменения из тайника. Таким образом, вы можете даже вручную отредактировать куски, что немного больно, когда в git add -p:

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

Использование метода stash дает вам возможность протестировать, если ваш код все еще работает, прежде чем выполнить его.

  • 0
    это работает хорошо, но если вы используете git commit --amend , то кажется, что вы не можете git commit --amend тайник впоследствии, или есть способ сделать это?
7

Intellij IDEA (и я полагаю, что все остальные продукты серии) построили поддержку частичных коммитов, поскольку v2018.1

Изображение 7493

7

Для тех, кто использует Git Расширения:

В окне "Копировать" выберите файл, который вы хотите частично совершить, затем выберите текст, который вы хотите зафиксировать, в правой панели, затем щелкните правой кнопкой мыши на выделенном фрагменте и выберите "Сформировать выбранные строки" в контекстном меню.

  • 1
    Ярлык клавиатуры в Git Extensions для «Stage выбранных линий» является s - очень полезно для быстрой постановки части файлов для фиксации.
6

vim-gitgutter плагин может создавать ханки, не выходя из редактора vim, используя

:GitGutterStageHunk

Помимо этого, он предоставляет другие интересные функции, такие как столбец с разным знаком, как в некоторых современных IDE

Если только часть hunk должна быть поставлена ​​vim-fugitive

:Gdiff

позволяет выбирать диапазон видимого диапазона, затем :'<,'>diffput или :'<,'>diffget для изменения/изменения отдельных строк.

5

Попробовал git add -p filename.x, но на Mac я обнаружил, что gitx (http://gitx.frim.nl/ или https://github.com/pieter/gitx) гораздо проще совершить точно линии, которые я хотел.

4

С TortoiseGit:

щелкните правой кнопкой мыши файл и используйте Context Menu → Restore after commit. Это создаст копию файла, как есть. Затем вы можете отредактировать файл, например. в TortoiseGitMerge и отмените все изменения, которые вы не хотите совершать. После сохранения этих изменений вы можете зафиксировать файл.

2

git-meld-index - цитирование с веб-сайта:

git -meld-index запускает meld - или любой другой git diffftool (kdiff3, diffuse и т.д.) - чтобы вы могли интерактивно изменять изменения индекса git (также известного как git).

Это похоже на функциональность git add -p и git add --interactive. В некоторых случаях meld легче/быстрее использовать, чем git add -p. Это потому, что meld позволяет вам, например,:

  • см. больше контекста
  • см. внутрилинейные различия
  • отредактируйте вручную и посмотрите 'live' diff updates (обновляется после каждого нажатия клавиши)
  • перейдите к изменению, не указывая "n" на каждое изменение, которое вы хотите пропустить.

Использование

В репозитории git запустите:

git meld-index

Вы увидите, что meld (или настроенный git diffftool) появляется с помощью

LEFT: файлы временного каталога, скопированные из рабочего дерева

ВПРАВО: временный каталог с содержимым индекса. Это также включает файлы, которые еще не находятся в индексе, но изменены или не проверены в рабочей копии - в этом случае вы увидите содержимое файла из HEAD.

Отредактируйте индекс (справа) до тех пор, пока он не станет счастливым. Не забудьте сохранить при необходимости.

Когда вы закончите, закройте meld и git -meld-index обновит индекс, чтобы он соответствовал содержимому временного каталога в правой части команды meld, которую вы только что отредактировали.

2

Для emacs также есть gitsum

1

Добавляя предыдущий ответ, если вы предпочитаете использовать командную строку, введите git add -e myfile дает вам выбор, чтобы выбрать строку за строкой, которую вы хотите зафиксировать, потому что эта команда откроет редактор с различиями, например:

Изображение 7494

Как вы можете видеть, строки, начинающиеся с + - это addtions, строки, которые начинаются с - это удаления. Так:

  • Чтобы не сгенерировать дополнение, просто удалите эту строку.
  • Чтобы не выполнить удаление просто замените - пробелом ,

Это то, что git add -h говорит о добавлении файлов таким образом (файлы исправлений):

добавленный контент Добавленный контент представлен строками, начинающимися с "+". Вы можете предотвратить установку любых линий сложения, удалив их.

Удаленный контент: Удаленное содержимое представлено строками, начинающимися с "-". Вы можете предотвратить их удаление путем преобразования "-" в "" (пробел).

измененное содержимое. Измененный контент представлен линиями "-" (удаление старого содержимого), а затем строки "+" (добавление замещающего содержимого). Вы можете предотвратить установку модификации путем преобразования строк "-" в "" и удаления строк "+". Помните, что изменение только половины пары, вероятно, приведет к запутывающим изменениям индекса.

Внимание: не изменяйте содержимое файла, это нехорошее место для этого. Просто измените операторы удаленных или добавленных строк.

1

Для пользователей Atom пакет github включает интерактивную постановку в стиле git gui. Для ярлыков см. Документацию к упаковке.

Использование Atom позволяет работать с темой с темным фоном (по умолчанию git gui имеет белый фон).

1

Как один ответ выше показывает, вы можете использовать git add --patch filename.txt

или короткая форма git add -p filename.txt

... но для файлов, уже находящихся в вашем репозитории, есть намного лучше использовать флаг -patch для команды commit (если вы используете достаточно недавнюю версию git): git commit --patch filename.txt

... или, опять же, короткая форма git commit -p filename.txt

... и затем используя указанные ключи (y/n и т.д.), для выбора строк, которые должны быть включены в фиксацию.

  • 0
    Что это дает вам над " git add -p filename.txt " помимо меньшего места для ошибки? Если вы испортили частичное изменение файла, отмена добавления лучше, чем отмена фиксации.
  • 0
    Я не знаю почему, но когда я говорю «n», строка включается… и когда я говорю «y» на втором блоке, она также включается.
0

git-cola - отличный графический интерфейс, а также встроенная функция. Просто выберите линии для сцены и нажмите S. Если выбор не производится, выполняется полный кусок.

0

Если на платформе Windows, на мой взгляд, git gui - лучший инструмент для stage/commit нескольких строк из unstaged файла

1. Хенк мудрый:

  • Выберите файл из раздела unstagged Changes
  • Щелкните правой кнопкой мыши код кода, который необходимо выполнить.
  • Выберите Stage Hunk for commit

2. Строка:

  • Выберите файл из раздела unstagged Changes
  • Выберите строку/строки, которые будут организованы
  • Выберите Stage Lines for commit

3. Если вы хотите создать полный файл, кроме пары строк:

  • Выберите файл из раздела unstagged Changes
  • Нажмите Ctrl+T (Stage file to commit)
  • Выбранный файл теперь перемещается в Staged Changes Раздел
  • Выберите строку/строки, которые будут организованы
  • Выберите UnStage Lines for commit

Ещё вопросы

Сообщество Overcoder
Наверх
Меню