1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
== Базовые операции ==
Прежде чем погружаться в дебри многочисленных команд Git, попробуйте воспользоваться приведенными ниже простыми примерами, чтобы немного освоиться. Каждый из них полезен, несмотря на свою простоту. На самом деле первые месяцы использования Git я не выходил за рамки материала этой главы.
=== Сохранение состояния ===
Собираетесь попробовать внести некие радикальные изменения? Предварительно создайте снимок всех файлов в текущем каталоге с помощью команд
$ git init
$ git add .
$ git commit -m "Моя первая резервная копия"
Теперь, если новые правки всё испортили, можно восстановить первоначальную версию:
$ git reset --hard
Чтобы вновь сохранить состояние:
$ git commit -a -m "Другая резервная копия"
=== Добавление, удаление, переименование ===
Приведенный выше пример отслеживает только те файлы, которые существовали при первом запуске *git add*. Если вы создали новые файлы или подкаталоги, придется сказать Git'у:
$ git add readme.txt Documentation
Аналогично, если хотите, чтобы Git забыл о некоторых файлах:
$ git rm ляп.h старье.c
$ git rm -r улики/
Git удалит эти файлы, если вы не удалили их сами.
Переименование файла — это то же, что удаление старого имени и добавления нового. Для этого есть *git mv*, которая имеет тот же синтаксис, что и команда *mv*. Например:
$ git mv bug.c feature.c
=== Расширенные отмена/возврат ===
Иногда просто хочется вернуться назад и забыть все изменения до определенного момента, потому что все они были неправильными. В таком случае
$ git log
покажет список последних коммитов и их хеши SHA1:
----------------------------------
commit 766f9881690d240ba334153047649b8b8f11c664
Author: Bob <bob@example.com>
Date: Tue Mar 14 01:59:26 2000 -0800
Заменил printf() на write().
commit 82f5ea346a2e651544956a8653c0f58dc151275c
Author: Alice <alice@example.com>
Date: Thu Jan 1 00:00:00 1970 +0000
Начальный коммит.
----------------------------------
Для указания коммита достаточно первых нескольких символов его хеша, но можете скопировать и весь хеш. Наберите:
$ git reset --hard 766f
для восстановления состояния до указанного коммита и удаления всех последующих безвозвратно.
Возможно, в другой раз вы захотите быстро перескочить к старому состоянию. В этом случае наберите
$ git checkout 82f5
Эта команда перенесет вас назад во времени, сохранив при этом более новые коммиты. Однако, как и в фантастических фильмах о путешествиях во времени, если теперь вы отредактируете и закоммитите код, то попадете в альтернативную реальность, потому что ваши действия отличаются от тех, что были в прошлый раз.
Эта альтернативная реальность называется «веткой» (branch, прим. пер.), и <<branch,чуть позже мы поговорим об этом подробнее>>. А сейчас просто запомните, что команда
$ git checkout master
вернет вас обратно в настоящее. Кроме того, чтобы не получать предупреждений от Git, всегда делайте commit или сбрасывайте изменения перед запуском checkout.
Еще раз воспользуемся аналогией с компьютерными играми:
- *git reset --hard*: загружает ранее сохраненную игру и удаляет все версии, сохраненные после только что загруженной.
- *git checkout*: загружает старую игру, но если вы продолжаете играть, состояние игры будет отличаться от более новых сохранений, которые вы сделали в первый раз. Любая игра, которую вы теперь сохраняете, попадает в отдельную ветку, представляющую альтенативную реальность, в которую вы попали. <<branch,Мы обсудим это позже>>.
Можно также восстановить только определенные файлы и подкаталоги, перечислив их имена после команды:
$ git checkout 82f5 какой-то.файл другой.файл
Будьте внимательны: такая форма *checkout* может молча перезаписать файлы. Чтобы избежать неприятных неожиданностей, выполняйте commit перед checkout, особенно если вы только изучаете Git. Вообще, если вы не уверены в какой-либо операции, будь то команда Git или нет, выполните предварительно *git commit -a*.
Не любите копировать и вставлять хеши? Используйте
$ git checkout :/"Моя первая р"
для перехода на коммит, чье описание начинается с приведенной строки.
Можно также запросить 5-ое с конца сохраненное состояние:
$ git checkout master~5
=== Откаты ===
В зале суда пункты протокола могут вычеркиваться прямо во время слушания. Подобным образом и вы можете выбирать коммиты для отмены.
$ git commit -a
$ git revert 1b6d
отменит коммит с заданным хешем. Откат будет сохранен в виде нового коммита. Можете запустить *git log*, чтобы убедиться в этом.
=== Создание списка изменений ===
Некоторым проектам нужен http://en.wikipedia.org/wiki/Changelog[список изменений] (changelog, прим. пер.). Создайте его такой командой:
$ git log > ChangeLog
=== Скачивание файлов ===
Получить копию проекта под управлением Git можно, набрав
$ git clone git://сервер/путь/до/файлов
Например, чтобы получить все файлы, которые я использовал для создания этого документа,
$ git clone git://git.or.cz/gitmagic.git
Позже мы поговорим о команде *clone* подробнее.
=== Держа руку на пульсе ===
Если вы уже загрузили копию проекта с помощью *git clone*, можете обновить ее до последней версии, используя
$ git pull
=== Безотлагательная публикация ===
Допустим, вы написали скрипт, которым хотите поделиться с другими. Можно просто предложить им скачивать его с вашего компьютера, но если они будут делать это когда вы дорабатываете его или добавляете экспериментальную функциональность, у них могут возникнуть проблемы. Очевидно, поэтому и существуют циклы разработки. Разработчики могут постоянно работать над проектом, но общедоступным они делают свой код только после того, как приведут его в приличный вид.
Чтобы сделать это с помощью Git, выполните в каталоге, где лежит ваш скрипт,
$ git init
$ git add .
$ git commit -m "Первый релиз"
Затем скажите вашим пользователям запустить
$ git clone ваш.компьютер:/путь/до/скрипта
чтобы загрузить ваш скрипт. Здесь подразумевается, что у них есть доступ по ssh. Если нет, запустите *git daemon* и скажите пользователям запустить эту команду вместо вышеприведенной:
$ git clone git://ваш.компьютер/путь/до/скрипта
С этих пор всякий раз, когда ваш скрипт готов к релизу, выполняйте
$ git commit -a -m "Следующий релиз"
и ваши пользователи смогут обновить свои версии, перейдя в каталог, с вашим скриптом и набрав
$ git pull
Ваши пользователи никогда не наткнутся на версию скрипта, которую вы не хотите им показывать.
=== Что я сделал? ===
Выясните, какие изменения вы сделали со времени последнего коммита:
$ git diff
Или со вчерашнего дня:
$ git diff "@{yesterday}"
Или между определенной версией и версией, сделанной 2 коммита назад:
$ git diff 1b6d "master~2"
В каждом случае на выходе будет патч, который может быть применен с помощью *git apply*. Попробуйте также:
$ git whatchanged --since="2 weeks ago"
Часто вместо этого я использую для просмотра истории http://sourceforge.net/projects/qgit[qgit], из-за приятного интерфейса, или http://jonas.nitro.dk/tig[tig] с текстовым интерфейсом, который хорошо работает через медленное соединение. Как вариант, установите веб-сервер, введите *git instaweb* и запустите любой веб-браузер.
=== Упражнение ===
Пусть A, B, C, D — четыре последовательных коммита, где В отличается от A лишь несколькими удаленными файлами. Мы хотим вернуть эти файлы в D. Как мы можем это сделать?
Существует как минимум три решения. Предположим, что мы находимся на D.
1. Разница между A и B — удаленные файлы. Мы можем создать патч, отражающий эти изменения, и применить его:
$ git diff B A | git apply
2. Поскольку в коммите A мы сохранили файлы, то можем восстановить их:
$ git checkout A foo.c bar.h
3. Мы можем рассматривать переход от A к B как изменения, которые хотим отменить:
$ git revert B
Какой способ лучше? Тот, который вам больше нравится. С помощью Git легко получить желаемое, и часто существует много способов это сделать.
|