Статьи

Частичные коммиты с Git

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

Я работаю над своей новой большой вещью; калькулятор командной строки. Я уже сделал сложение и вполне доволен этим, и теперь я делаю вычитание. На полпути реализации вычитания я обнаружил, что мне нужно внести некоторые изменения в класс форматера консоли вывода. Он имеет +жестко закодированный знак и теперь должен принимать это как параметр. Я делаю это и получаю рабочее решение.

Делать git statusоднако показывает беспорядок.

C:\git\spikes\gitpartial [master +1 ~2 -0 !]> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
        modified:   ConsoleFormatter.cs
        modified:   Program.cs
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
        Subtraction.cs
 
no changes added to commit (use "git add" and/or "git commit -a")
C:\git\spikes\gitpartial [master +1 ~2 -0 !]>

У меня есть и обновленное ConsoleFormatter.cs, обновленное Program.csи новое Subtraction.cs. Первый содержит обновленные функции форматирования консоли, которые не зависят от добавленной функциональности. Я хочу совершить ConsoleFormmatter.csотдельно. И не только совершить это. Я хочу скомпилировать и протестировать точный код, который я собираюсь зафиксировать, скрыв другие файлы от просмотра. С помощью git это можно сделать всего несколькими командами. С Subversion я так и не понял, как сделать это достаточно простым способом. Я обычно заканчиваю одним большим коммитом на SVN. Если кто-нибудь знает, как сделать это так просто в SVN, пожалуйста, оставьте комментарий.

Постановка Разыскиваемых Изменений

Первым шагом является внесение необходимых изменений в первый коммит.

C:\git\spikes\gitpartial [master +1 ~2 -0 !]> git add ConsoleFormatter.cs
C:\git\spikes\gitpartial [master +0 ~1 -0 | +1 ~1 -0 !]>

Выполнение a git statusпоказывает, что ConsoleFormatter.csфайл теперь готов к фиксации.

C:\git\spikes\gitpartial [master +0 ~1 -0 | +1 ~1 -0 !]> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
 
        modified:   ConsoleFormatter.cs
 
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
        modified:   Program.cs
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
        Subtraction.cs
 
C:\git\spikes\gitpartial [master +0 ~1 -0 | +1 ~1 -0 !]>

Скрытие других изменений

Теперь пришло время скрыть другие изменения от просмотра git stash.

C:\git\spikes\gitpartial [master +0 ~1 -0 | +1 ~1 -0 !]> git stash -u -k
Saved working directory and index state WIP on master: 0b093c1 Implemented addition.
HEAD is now at 0b093c1 Implemented addition.
C:\git\spikes\gitpartial [master +0 ~1 -0]>

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

Повторное выполнение git statusпоказывает только ConsoleFormatter.csфайл, который я хочу зафиксировать на первом шаге. Это не просто мерзавец. Это фактическое содержимое рабочего каталога. На этом этапе я могу скомпилировать и протестировать код, который я собираюсь проверить, чтобы убедиться, что он действительно работает без обновленного файла Program.cs.

C:\git\spikes\gitpartial [master +0 ~1 -0]> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
 
        modified:   ConsoleFormatter.cs
 
C:\git\spikes\gitpartial [master +0 ~1 -0]>

Создание двух комитетов

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

C:\git\spikes\gitpartial [master +0 ~1 -0]> git commit -m "Improved ConsoleFormatter."
[master d69baee] Improved ConsoleFormatter.
 1 file changed, 0 insertions(+), 0 deletions(-)
C:\git\spikes\gitpartial [master]>

Время вернуть другие изменения.

C:\git\spikes\gitpartial [master]> git stash pop
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
        modified:   Program.cs
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
        Subtraction.cs
 
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1bd32daf6787280201ccdacb90bc76e1ca45e7ce)
C:\git\spikes\gitpartial [master +1 ~1 -0 !]>

И совершить их.

C:\git\spikes\gitpartial [master +1 ~1 -0 !]> git add .
C:\git\spikes\gitpartial [master +1 ~1 -0]> git commit -m "Implemented Subtraction."
[master 46f2e66] Implemented Subtraction.
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 Subtraction.cs
C:\git\spikes\gitpartial [master]>

Результат

Результатом является хорошая история коммитов, где отдельные изменения находятся в отдельных коммитах.

 
C:\git\spikes\gitpartial [master]> git log --stat
commit 46f2e66f69dac06ce111f3ab13c6ec68d9b9fae2 (HEAD, master)
Author: Anders Abel <anders@abel.nu>
Date:   Thu Oct 16 22:18:02 2014 +0200
 
    Implemented Subtraction.
 
 Program.cs     | Bin 12 -> 22 bytes
 Subtraction.cs | Bin 0 -> 12 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 
commit d69baeeb4b753779bdc3706730e9162244b6e355
Author: Anders Abel <anders@abel.nu>
Date:   Thu Oct 16 22:17:47 2014 +0200
 
    Improved ConsoleFormatter.
 
 ConsoleFormatter.cs | Bin 12 -> 22 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 
commit 0b093c1dcb7a536a40648e2977fb73edef9200d5
Author: Anders Abel <anders@abel.nu>
Date:   Thu Oct 16 22:03:53 2014 +0200
 
    Implemented addition.
 
 Addition.cs         | Bin 0 -> 12 bytes
 ConsoleFormatter.cs | Bin 0 -> 12 bytes
 Program.cs          | Bin 0 -> 12 bytes
 3 files changed, 0 insertions(+), 0 deletions(-)
C:\git\spikes\gitpartial [master]>

(И количество байтов правильное. Я обманул, это не настоящий код в этих файлах.)