11 концепций и команд git, которые заставят вас плакать


Оглавление (нажмите, чтобы открыть):

.2 Основы Git — Запись изменений в репозиторий

Запись изменений в репозиторий

Итак, у вас имеется настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта. Вам нужно делать некоторые изменения и фиксировать “снимки” состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить.

Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые). Отслеживаемые файлы — это те файлы, которые были в последнем слепке состояния проекта (snapshot); они могут быть неизменёнными, изменёнными или подготовленными к коммиту (staged). Неотслеживаемые файлы — это всё остальное, любые файлы в вашем рабочем каталоге, которые не входили в ваш последний слепок состояния и не подготовлены к коммиту. Когда вы впервые клонируете репозиторий, все файлы будут отслеживаемыми и неизменёнными, потому что вы только взяли их из хранилища (checked them out) и ничего пока не редактировали.

Как только вы отредактируете файлы, Git будет рассматривать их как изменённые, т.к. вы изменили их с момента последнего коммита. Вы индексируете (stage) эти изменения и затем фиксируете все индексированные изменения, а затем цикл повторяется. Этот жизненный цикл изображён на рисунке 2-1.

Рисунок 2-1. Жизненный цикл состояний файлов.

Определение состояния файлов

Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это команда git status . Если вы выполните эту команду сразу после клонирования, вы увидите что-то вроде этого:

Это означает, что у вас чистый рабочий каталог, другими словами — в нём нет отслеживаемых изменённых файлов. Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь. И наконец, команда сообщает вам на какой ветке (branch) вы сейчас находитесь. Пока что это всегда ветка master — это ветка по умолчанию; в этой главе это не важно. В следующей главе будет подробно рассказано про ветки и ссылки.

Предположим, вы добавили в свой проект новый файл, простой файл README. Если этого файла раньше не было, и вы выполните git status , вы увидите свой неотслеживаемый файл вот так:

Понять, что новый файл README неотслеживаемый можно по тому, что он находится в секции «Untracked files» в выводе команды status . Статус «неотслеживаемый файл», по сути, означает, что Git видит файл, отсутствующий в предыдущем снимке состояния (коммите); Git не станет добавлять его в ваши коммиты, пока вы его явно об этом не попросите. Это предохранит вас от случайного добавления в репозиторий сгенерированных бинарных файлов или каких-либо других, которые вы и не думали добавлять. Мы хотели добавить README, так давайте сделаем это.

Отслеживание новых файлов

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add . Чтобы начать отслеживание файла README, вы можете выполнить следующее:

Если вы снова выполните команду status , то увидите, что файл README теперь отслеживаемый и индексированный:

Вы можете видеть, что файл проиндексирован по тому, что он находится в секции “Changes to be committed”. Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add , будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее выполнили git init , вы затем выполнили git add (файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль. Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет (индексирует) все файлы в данном каталоге.

Индексация изменённых файлов

Давайте модифицируем файл, уже находящийся под версионным контролем. Если вы измените отслеживаемый файл benchmarks.rb и после этого снова выполните команду status , то результат будет примерно следующим:

Файл benchmarks.rb находится в секции “Changes not staged for commit” — это означает, что отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован. Чтобы проиндексировать его, необходимо выполнить команду git add (это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния). Выполним git add , чтобы проиндексировать benchmarks.rb, а затем снова выполним git status :

Теперь оба файла проиндексированы и войдут в следующий коммит. В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в benchmarks.rb до фиксации. Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту. Но давайте-ка ещё раз выполним git status :

Что за чёрт? Теперь benchmarks.rb отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add . Если вы выполните коммит сейчас, то файл benchmarks.rb попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add , а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit . Если вы изменили файл после выполнения git add , вам придётся снова выполнить git add , чтобы проиндексировать последнюю версию файла:

Игнорирование файлов

Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых. К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т.п.). В таком случае, вы можете создать файл .gitignore с перечислением шаблонов соответствующих таким файлам. Вот пример файла .gitignore:

Первая строка предписывает Git’у игнорировать любые файлы заканчивающиеся на .o или .a — объектные и архивные файлы, которые могут появиться во время сборки кода. Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (

), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов. Вы можете также включить каталоги log, tmp или pid; автоматически создаваемую документацию; и т.д. и т.п. Хорошая практика заключается в настройке файла .gitignore до того, как начать серьёзно работать, это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите.

К шаблонам в файле .gitignore применяются следующие правила:

  • Пустые строки, а также строки, начинающиеся с #, игнорируются.
  • Можно использовать стандартные glob шаблоны.
  • Можно заканчивать шаблон символом слэша ( / ) для указания каталога.
  • Можно инвертировать шаблон, использовав восклицательный знак ( ! ) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения используемые командными интерпретаторами. Символ * соответствует 0 или более символам; последовательность [abc] — любому символу из указанных в скобках (в данном примере a, b или c); знак вопроса ( ? ) соответствует одному символу; [0-9] соответствует любому символу из интервала (в данном случае от 0 до 9).


Вот ещё один пример файла .gitignore:

Шаблон **/ доступен в Git, начиная с версии 1.8.2.

Просмотр индексированных и неиндексированных изменений

Если результат работы команды git status недостаточно информативен для вас — вам хочется знать, что конкретно поменялось, а не только какие файлы были изменены — вы можете использовать команду git diff . Позже мы рассмотрим команду git diff подробнее; вы, скорее всего, будете использовать эту команду для получения ответов на два вопроса: что вы изменили, но ещё не проиндексировали, и что вы проиндексировали и собираетесь фиксировать. Если git status отвечает на эти вопросы слишком обобщённо, то git diff показывает вам непосредственно добавленные и удалённые строки — собственно заплатку (patch).

Допустим, вы снова изменили и проиндексировали файл README, а затем изменили файл benchmarks.rb без индексирования. Если вы выполните команду status , вы опять увидите что-то вроде:

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff без аргументов:

Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса. Результат показывает ещё не проиндексированные изменения.

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff —cached . (В Git’е версии 1.6.1 и выше, вы также можете использовать git diff —staged , которая легче запоминается.) Эта команда сравнивает ваши индексированные изменения с последним коммитом:

Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что ещё не проиндексированы. Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернёт.

Мастер Йода рекомендует:  Как разрабатывать приложения смешанной реальности для Microsoft HoloLens создание проекта Unity 3D

Другой пример: вы проиндексировали файл benchmarks.rb и затем изменили его, вы можете использовать git diff для просмотра как индексированных изменений в этом файле, так и тех, что пока не проиндексированы:

Теперь вы можете используя git diff посмотреть непроиндексированные изменения

а также уже проиндексированные, используя git diff —cached :

Фиксация изменений

Теперь, когда ваш индекс настроен так, как вам и хотелось, вы можете зафиксировать свои изменения. Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или изменённые вами, и для которых вы не выполнили git add после момента редактирования — не войдут в этот коммит. Они останутся изменёнными файлами на вашем диске. В нашем случае, когда вы в последний раз выполняли git status , вы видели что всё проиндексировано, и вот, вы готовы к коммиту. Простейший способ зафиксировать изменения — это набрать git commit :

Эта команда откроет выбранный вами текстовый редактор. (Редактор устанавливается системной переменной $EDITOR — обычно это vim или emacs, хотя вы можете установить ваш любимый с помощью команды git config —global core.editor , как было показано в главе 1).

В редакторе будет отображён следующий текст (это пример окна Vim’а):

Вы можете видеть, что комментарий по умолчанию для коммита содержит закомментированный результат работы («выхлоп») команды git status и ещё одну пустую строку сверху. Вы можете удалить эти комментарии и набрать своё сообщение или же оставить их для напоминания о том, что вы фиксируете. (Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент -v в команду git commit . Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть всё, что сделано.) Когда вы выходите из редактора, Git создаёт для вас коммит с этим сообщением (удаляя комментарии и вывод diff’а).

Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit , указав его после параметра -m, как в следующем примере:

Итак, вы создали свой первый коммит! Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит (master), какая контрольная сумма SHA-1 у этого коммита ( 463dc4f ), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите.

Запомните, что коммит сохраняет снимок состояния вашего индекса. Всё, что вы не проиндексировали, так и торчит в рабочем каталоге как изменённое; вы можете сделать ещё один коммит, чтобы добавить эти изменения в репозиторий. Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние.

Игнорирование индексации

Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими, как вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы. Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ. Добавление параметра -a в команду git commit заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add :

Обратите внимание на то, что в данном случае перед коммитом вам не нужно выполнять git add для файла benchmarks.rb.

Удаление файлов

Для того чтобы удалить файл из Git’а, вам необходимо удалить его из отслеживаемых файлов (точнее, удалить его из вашего индекса) а затем выполнить коммит. Это позволяет сделать команда git rm , которая также удаляет файл из вашего рабочего каталога, так что вы в следующий раз не увидите его как “неотслеживаемый”.

Если вы просто удалите файл из своего рабочего каталога, он будет показан в секции “Changes not staged for commit” (“Изменённые но не обновлённые” — читай не проиндексированные) вывода команды git status :

Затем, если вы выполните команду git rm , удаление файла попадёт в индекс:

После следующего коммита файл исчезнет и больше не будет отслеживаться. Если вы изменили файл и уже проиндексировали его, вы должны использовать принудительное удаление с помощью параметра -f . Это сделано для повышения безопасности, чтобы предотвратить ошибочное удаление данных, которые ещё не были записаны в снимок состояния и которые нельзя восстановить из Git’а.


Другая полезная штука, которую вы можете захотеть сделать — это удалить файл из индекса, оставив его при этом в рабочем каталоге. Другими словами, вы можете захотеть оставить файл на винчестере, и убрать его из-под бдительного ока Git’а. Это особенно полезно, если вы забыли добавить что-то в файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компиляции. Чтобы сделать это, используйте опцию —cached :

В команду git rm можно передавать файлы, каталоги или glob-шаблоны. Это означает, что вы можете вытворять что-то вроде:

Обратите внимание на обратный слэш ( \ ) перед * . Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора. Эта команда удаляет все файлы, которые имеют расширение .log в каталоге log/ . Или же вы можете сделать вот так:

Эта команда удаляет все файлы, чьи имена заканчиваются на

Перемещение файлов

В отличие от многих других систем версионного контроля, Git не отслеживает перемещение файлов явно. Когда вы переименовываете файл в Git’е, в нём не сохраняется никаких метаданных, говорящих о том, что файл был переименован. Однако, Git довольно умён в плане обнаружения перемещений постфактум — мы рассмотрим обнаружение перемещения файлов чуть позже.

Таким образом, наличие в Git’е команды mv выглядит несколько странным. Если вам хочется переименовать файл в Git’е, вы можете сделать что-то вроде:

и это отлично сработает. На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла:

Однако, это эквивалентно выполнению следующих команд:

Git неявно определяет, что произошло переименование, поэтому неважно, переименуете вы файл так или используя команду mv . Единственное отличие состоит лишь в том, что mv — это одна команда вместо трёх — это функция для удобства. Важнее другое — вы можете использовать любой удобный способ, чтобы переименовать файл, и затем воспользоваться add/rm перед коммитом.

11 концепций и команд git, которые заставят вас плакать

При работе с Git может возникнуть такая ситуация: команда git push не заливает изменения на сервер, а команда git status показывает:

HEAD detached from 87dc87b

Э то может означать, что вы делали какую-то навигацию по истории коммитов, и неправильно вернулись к последнему коммиту.

Исправить эту проблему можно 4-мя командами:

git branch temp
git checkout temp
git branch -f master temp
git checkout master

git branch -d temp

Что при этом происходит:

1. создаем временную ветку с именем temp, причем в новой ветке будет правильно установлено положение HEAD
2. переключаемся на временную ветку temp
3. в ветке master устанавливается та же позиция HEAD, что и в ветке temp
4. переключиться на ветку master

5. удалить временную ветку

Еще один вариант, короткий

git checkout имяВеткиГдеВыНаходитесь

— эта команда переключит проект в последний коммит текущей ветки. Точнее, в состоянии detached head, проект не находится ни в какой ветке. git checkout branchname просто переключит проект на последний коммит той ветки, которая указана. Это значит, что до появления ошибки нужно знать, в какой ветке ты находишься. Для того чтобы посмотреть, где находился, можно воспользовтьася командой:

Полезные команды Git: безопасная отмена коммитов, добавление файла из другой ветки и другие

Git — это мощный, хотя и незамысловато выглядящий, инструмент, который при неосторожном использовании может устроить большой беспорядок. Поэтому, прежде чем пробовать выполнять различные фокусы с Git, я рекомендую ознакомиться с его основными командами (init, clone, push, pull, status, log и т.д.) и концептами (репозиторий, ветвь, коммит, и т.д.).

Итак, если вы уверенно чувствуете себя при работе с Git, вот несколько полезных трюков, о которых я знаю.

Reflog. Отмена операций


Я помню, что в начале знакомства с Git я боялся запускать команды. Я думал, что всё испорчу. Например, первое использование git rebase вызвало у меня несколько восклицаний наподобие «Вот *****! Что я только что сделал?!» из-за дублировавшихся или вообще исчезнувших коммитов. Вскоре после этого я понял, что нужно идти дальше.

Лично я не люблю использовать инструмент, не зная, что именно он делает для достижения результата. Это как вождение машины без руля: всё прекрасно до тех пор, пока не доедешь до поворота. А что потом? Ну, вы меня поняли.

Итак, в нашем деле очень важно понимать концепты. Я много читал про Git, прошёл несколько обучающих курсов, и моё видение мира Git кардинально изменилось. Используя его, я стал чувствовать себя гораздо спокойнее, а что более важно, я познал его истинную мощь. И одной из самых мощных команд является git reflog .

«Бастион», Москва, от 80 000 до 200 000 ₽

Используя reflog , вы можете вернуться в прошлое, отменяя почти любые действия, сделанные в Git. Даже если это были rebase или reset . Кроме того, её легко использовать. Чтобы доказать это, приведу маленький пример.

Чтобы изменить нужное состояние, нужно запустить checkout , используя абсолютную ссылку:

или относительную ссылку:

и вы окажетесь в независимом (detached) состоянии HEAD, из которого можно создать новую ветвь.

Вот и всё. Все операции после вышеуказанного состояния отменены.

Revert. Отмена изменений коммита

Вы, должно быть, сталкивались с ситуацией, когда вам нужно было отменить некоторые изменения. На помощь придёт команда revert :

Что она делает? Она просто отменяет действия прошлых коммитов, создавая новый, содержащий все отменённые изменения. Зачем использовать её вместо других решений? Это — единственный безопасный способ, так как он не изменяет историю коммитов. Он обычно используется в публичных ветвях, где изменение истории нежелательно.

Мастер Йода рекомендует:  devnull не нужен пишем бота на Python, который будет присылать свежие мемасики

Давайте взглянем на другие команды, способные отменять действия.

Rebase

Вы можете выполнить эту команду и просто убрать строки, относящиеся к ненужным коммитам. Это самое очевидное и простое решение, но у него есть недостаток, из-за которого его нельзя использовать в публичных ветвях: он изменяет историю коммитов. Поэтому после rebase’а у вас может возникнуть проблема с push’ем.

Reset

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

Checkout

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

Вывод таков, что git revert — самая безопасная операция для отмены действий. Кроме того, нужно заметить, что эти команды не взаимозаменяемы в 100% случаев.

Log. Более приятное форматирование

С git log всё просто. Вы вводите команду и видите историю коммитов в хронологическом порядке, и каждый пункт включает в себя хэш коммита, автора, дату и прикреплённое сообщение.

Давайте взглянем на вид лога по умолчанию:

Я думаю, что могло бы быть и лучше.

Я предпочитаю простые вещи. Поэтому я использую две опции:

  • —oneline – показывает каждый коммит в одной строке. Кроме того, она показывает лишь префикс ID коммита.
  • —decorate – печатает все относительные имена показанных коммитов.

Вот как это выглядит:


Опция —oneline сокращает количество занятых строк, а опция —decorate добавляет относительные имена (локальные/удалённые ветви + HEAD). Используя эти две опции, мы получаем более компактный и осмысленный git log . Да, мы теряем некоторые вещи, но они не особо важны. Так гораздо лучше, да?

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

Ничего себе! Давайте посмотрим, как это выглядит:

И всё-таки вводить эти команды каждый раз достаточно неудобно, так? Давайте создадим алиасы. Я считаю, что использование алиасов очень сильно повышает продуктивность. Чтобы зарегистрировать их, добавим следующие строки в «

/.bash_profile» (конечно, если вы используете *nix OS):

Таким образом, мы получили не только хорошо выглядящую историю коммитов, но и упрощённый способ доступа к ней, используя команды gl и gh .

Еще один вариант украшения вывода лога приведен в этой статье.

Diff. Разница между коммитами

Простая команда, показывающая изменения между объектами в проекте — git diff . Один из основных сценариев её использования — сравнение двух коммитов:

Другой — вывод всех изменений, не внесённых в индекс. Для этого нужно выполнить следующее:

Branch. Проверка ветвей на слияние

Я думаю, вы уже знаете, что делает базовая команда git branch (без опций выводит список локальных веток — прим. перев.), поэтому перейдём к делу. Время от времени вам понадобится удалять старые или ненужные ветви из вашего «дерева» git.

вы получите список всех веток, соединённых с текущей.

Можно и наоборот:

Так вы получите список всех не соединённых с текущей веток.

Таким образом, вы всегда узнаете, безопасно ли удаление той или иной ветви.

Checkout. Получение файла из другой ветви

Вам наверняка приходилось искать конкретную версию файла, которая была в другой, ещё не присоединённой ветви. Помните команду checkout , приведённую выше? Она выглядит так:

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

Надеюсь, вы нашли здесь для себя что-то полезное. Прошу заметить, что все вышеуказанные моменты субъективны, поскольку я подгонял их под свои нужды.

Как заставить Git merge в случае конфликта всегда брать theirs-правки?

Git меня задолбал. На сервере вдруг начались какие-то непонятные конфликты мерджей. При каждом таком конфликте merge marks просто рушат сервер.

Есть ли в конфигурации Git’а опции, которые бы заставляли его при каждом pull’е, если вдруг возникает конфликт merge, ВСЕГДА разрешать его только в сторону новой версии (параметр theirs при ручном слиянии) ?

  • Вопрос задан более трёх лет назад
  • 2807 просмотров


Если у вас на сервере делают коммиты, то:
git pull -X theirs

Если не делают, а просто файлы изменяются и потом не дают сделать нормально git pull, то:

11 записок экзистенциалиста, которые заставят вас смеяться и плакать одновременно

Большинство из нас время от времени настигает экзистенциальный кризис или кризис существования, когда кажется, что все бессмысленно, валится из рук и вы никогда не достигнете своих целей в жизни. Как ни странно, в такие минуты помогает черный юмор. И можно далеко не ходить, ведь все, что вам нужно, вы найдете в Instagram-аккаунте ‘Texts From Your Existentialist’, что в переводе означает «Смски от твоего экзистенциалиста». Напишите свои любимые в комментариях!

Шпаргалка по консольным командам Git

Dicta et ipsam iure qui distinctio qui qui sunt. Omnis doloremque omnis ullam doloremque non consequatur. Est amet itaque quisquam velit. Vero architecto error iure a debitis. Nisi quas pariatur non velit maxime animi dolore.

Consequatur distinctio culpa distinctio qui blanditiis. Et sequi aspernatur aut vitae.

Optio natus aut impedit deleniti architecto eum vel dolores. In sapiente facere voluptas beatae voluptas. Ut rem ex asperiores sit consequatur. Quia aliquid optio minima vero debitis. Eius est dolores nihil. Neque consectetur voluptas doloribus qui similique. Ratione facilis illo ullam impedit. Earum possimus facilis aut illum praesentium.

Autem dolores rerum eius consequatur eum. Numquam quasi in earum velit. Sint ea soluta autem eaque.

Quia doloremque quia dolores adipisci officiis temporibus et. Iusto sapiente inventore voluptatem at debitis quam voluptatem. Consequuntur architecto sequi nam sit necessitatibus. Sequi earum ducimus voluptates in voluptatem. Officiis sequi ut corrupti et ut. Ut perferendis qui in occaecati. Maiores tempore neque cupiditate qui.

Общее

Git — система контроля версий (файлов). Что-то вроде возможности сохраняться в компьютерных играх (в Git эквивалент игрового сохранения — коммит). Важно: добавление файлов к «сохранению» двухступенчатое: сначала добавляем файл в индекс ( git add ), потом «сохраняем» ( git commit ).

Любой файл в директории существующего репозитория может находиться или не находиться под версионным контролем (отслеживаемые и неотслеживаемые).

Отслеживаемые файлы могут быть в 3-х состояниях: неизменённые, изменённые, проиндексированные (готовые к коммиту).

Концепция GIT

Ключ к пониманию концепции git — знание о «трех деревьях»:

  • Рабочая директория — файловая система проекта (те файлы, с которыми вы работаете).
  • Индекс — список отслеживаемых git-ом файлов и директорий, промежуточное хранилище изменений (редактирование, удаление отслеживаемых файлов).
  • Директория .git/ — все данные контроля версий этого проекта (вся история разработки: коммиты, ветки, теги и пр.).

Коммит — «сохранение» (хранит набор изменений, сделанный в рабочей директории с момента предыдущего коммита). Коммит неизменен, его нельзя отредактировать.

У всех коммитов (кроме самого первого) есть один или более родительских коммитов, поскольку коммиты хранят изменения от предыдущих состояний.

Простейший цикл работ

  • Редактирование, добавление, удаление файлов (собственно, работа).
  • Индексация/добавление файлов в индекс (указание для git какие изменения нужно будет закоммитить).
  • Коммит (фиксация изменений).
  • Возврат к шагу 1 или отход ко сну.

Указатели


  • HEAD — указатель на текущий коммит или на текущую ветку (то есть, в любом случае, на коммит). Указывает на родителя коммита, который будет создан следующим.
  • ORIG_HEAD — указатель на коммит, с которого вы только что переместили HEAD (командой git reset . , например).
  • Ветка ( master , develop etc.) — указатель на коммит. При добавлении коммита, указатель ветки перемещается с родительского коммита на новый.
  • Теги — простые указатели на коммиты. Не перемещаются.

Настройки

Перед началом работы нужно выполнить некоторые настройки:

Если вы в Windows:

Указание неотслеживаемых файлов

Файлы и директории, которые не нужно включать в репозиторий, указываются в файле .gitignore . Обычно это устанавливаемые зависимости ( node_modules/ , bower_components/ ), готовая сборка build/ или dist/ и подобные, создаваемые при установке или запуске. Каждый файл или директория указываются с новой строки, возможно использование шаблонов.

Консоль

Длинный вывод в консоли: Vim

Вызов некоторых консольных команд приводит к необходимости очень длинного вывода в консоль (пример: вывод истории всех изменений в файле командой git log -p fileName.txt ). При этом прямо в консоли запускается редактор Vim. Он работает в нескольких режимах, из которых Вас заинтересуют режим вставки (редактирование текста) и нормальный (командный) режим. Чтобы попасть из Vim обратно в консоль, нужно в командном режиме ввести :q . Переход в командный режим из любого другого: Esc .

Если нужно что-то написать, нажмите i — это переход в режим вставки текста. Если нужно сохранить изменения, перейдите в командный режим и наберите :w .

15 команд Git, о которых вы, возможно, не знали

Перевод статьи «15 Git Commands You May Not Know».

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

Я хочу познакомить вас со списком из 15 команд Git, о которых вы, возможно, еще не знаете, но я надеюсь, что они вам пригодятся при освоении этого прекрасного инструмента.

1. Изменение последнего коммита

—amend позволяет добавлять подготовленные (staged) изменения к предыдущему коммиту (например, добавлять забытый файл). Если изменений нет, то —amend даст вам возможность переписать сообщение этого коммита (commit message). А если приписать —no-edit, то наоборот: можно будет внести изменения в сам коммит, не затрагивая commit message.

Узнать больше: git help commit

2. Интерактивное добавление отдельных частей файлов

-p (или —patch) позволяет интерактивно выбирать для добавления в коммит части отслеживаемый файлов. Таким образом коммит будет содержать только нужные изменения.

Мастер Йода рекомендует:  Викторины для программистов

Узнать больше: git help add

3. Интерактивное скрытие отдельных частей файлов

Опцию —patch можно добавлять не только к git-add. Добавленная к git stash, она позволяет интерактивно выбирать части отслеживаемых файлов, которые вы хотели бы скрыть.


Узнать больше: git help stash

4. Скрытие файлов, включая неотслеживаемые

По умолчанию при скрытии файлов неотслеживаемые файлы не учитываются. Чтобы изменить это поведение и включить в stash также и эти файлы, нужно использовать параметр -u. Есть также параметр -a (—all), который позволяет скрывать как неотслеживаемые, так и игнорируемые файлы, но это, вероятно, не то, что вам обычно нужно.

5. Интерактивный «сброс» выбранных частей файлов

—patch можно также использовать для выборочного сброса частей отслеживаемых файлов. Я задал этой команде псевдоним git discard.

Узнать больше: git help checkout

6. Переключение в предыдущую ветку

Эта команда позволяет вам быстро переключиться на ранее просматриваемую ветку. Знак дефиса это псевдоним предыдущей ветки. Его можно использовать и с другими командами.

7. Сброс всех локальных изменений

Если вы уверены, что все ваши локальные изменения можно сбросить, то для одновременного сброса вы можете использовать символ точки. Тем не менее, хорошей практикой будет всегда использовать checkout —patch.

8. Показать изменения

Эта команда показывает все подготовленные изменения (проиндексированные). Если вы введете просто git diff, будут показаны изменения только в рабочей директории.

Узнать больше: git help diff

9. Локальное переименование веток

Если вы хотите переименовать ветку, в которой находитесь на данный момент, можно сократить команду:

Узнать больше: git help branch

10. Переименование веток удаленно

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

11. Открыть все файлы с конфликтами одновременно

Перемещение (rebasing) может приводить к конфликтам. Следующая команда откроет все файлы, где нужно разрешить эти конфликты.

12. Что изменилось?

Эта команда покажет лог изменений, представленных по каждому коммиту за последние две недели.

13. Удаление файла из последнего коммита

Скажем, вы сделали коммит файла по ошибке. Этот файл можно быстро удалить из последнего коммита путем комбинации команд rm и commit —amend:

14. Поиск веток

Эта команда покажет все ветки, содержащие указанный коммит.

15. Локальная оптимизация репозитория

Узнать больше: git help gc


Бонус

Хотя мне очень нравится CLI, я настоятельно рекомендую обратить внимание на Magit, чтобы еще больше улучшить вашу работу с Git. Это одна из лучших программ, которые я использовал.

Кроме того, с помощью команды help можно получить совершенно фантастический обзор рекомендуемых рабочих процессов Git. Почитайте внимательно!

11 концепций и команд git, которые заставят вас плакать

При работе с Git может возникнуть такая ситуация: команда git push не заливает изменения на сервер, а команда git status показывает:

HEAD detached from 87dc87b

Э то может означать, что вы делали какую-то навигацию по истории коммитов, и неправильно вернулись к последнему коммиту.

Исправить эту проблему можно 4-мя командами:

git branch temp
git checkout temp
git branch -f master temp
git checkout master

git branch -d temp

Что при этом происходит:

1. создаем временную ветку с именем temp, причем в новой ветке будет правильно установлено положение HEAD
2. переключаемся на временную ветку temp
3. в ветке master устанавливается та же позиция HEAD, что и в ветке temp
4. переключиться на ветку master

5. удалить временную ветку

Еще один вариант, короткий

git checkout имяВеткиГдеВыНаходитесь

— эта команда переключит проект в последний коммит текущей ветки. Точнее, в состоянии detached head, проект не находится ни в какой ветке. git checkout branchname просто переключит проект на последний коммит той ветки, которая указана. Это значит, что до появления ошибки нужно знать, в какой ветке ты находишься. Для того чтобы посмотреть, где находился, можно воспользовтьася командой:

Какие основные задачи bare репозитория?

Насколько я понял, bare репозиторий создается как буфер между основной копией на сервере и ветками разработки.

Но не до конца понимаю, читая статью «удачная модель ветвления», зачем нужен этот тип репозитория, если все должно работать и так.

2 ответа 2

bare-репозиторий — это не какой-то особый тип репозитория. это, собственно, и есть репозиторий.

командой git init —bare в текущем каталоге создаётся именно репозиторий:

а вот командой git init (без опции —bare ) репозиторий создаётся в каталоге .git :

что позволяет использовать текущий каталог как рабочий каталог (working dir) с извлечёнными из репозитория файлами/каталогами, версии которых и отслеживаются этим самым репозиторием (вообще рабочий каталог может находиться в совершенно ином месте и указываться программе git с помощью опций -C или —work-tree или их комбинации (эти опции не эквивалентны), или переменной окружения GIT_WORK_TREE , или конфигурационной переменной core.worktree ).

«превратить» bare в не-bare (и обратно) очень легко: достаточно изменить значение ( true или false ) переменной bare в секции [core] файла config . вручную или командой git config core.bare значение . т.е., фактически, это некий признак, на практике означающий, что «рядом есть рабочий каталог с отслеживаемыми файлами».

зачем нужен этот признак?

чтобы при попытке «запушить» в текущую ветку (ту, на которую указывает содержимое файла HEAD ) «репозитория с рабочим каталогом» (не-bare-репозиторий) пользователь получал ошибку и подробное объяснение:


remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require ‘git reset —hard’ to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set ‘receive.denyCurrentBranch’ configuration variable to
remote: error: ‘ignore’ or ‘warn’ in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless yo
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: ‘receive.denyCurrentBranch’ configuration variable to ‘refuse’

мой вольный перевод:

отказано в обновлении ветки refs/heads/master , из которой извлечены файлы в рабочий каталог.

по умолчанию обновление текущей ветки в не-bare-репозитории запрещено, потому что это приведёт к несоответствию между тем, что вы «пушите», и индексом и содержимым рабочего каталога, и потребует выполнения git reset —hard для приведения рабочего каталога в соответствие с текущей веткой, т.е. той, которая указана в файле HEAD .

Команда Git stash. Как прятать изменения в Git

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

Для чего нужен git stash

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

Всё, что вы прячете с помощью git stash, попадает в отдельный список. Затем вы можете извлекать оттуда то, что вы туда спрятали — ваши «прятанья» (далее по тексту будет использоваться это слово).

Рассмотрим, как пользоваться командой git stash

Git stash

Чтобы спрятать изменения достаточно выполнить команду:

Git stash save

Команда git stash save выполняет то же самое, что и git stash , но имеет несколько полезных опций.

Например, можно сохранить изменения и добавить сообщение — подписать изменения, чтобы потом вспомнить, что именно было спрятано. В качестве сообщения, например, можно написать о том, какие именно изменения выполнены в файлах.

Git stash не прячет файлы, которые не добавлены в репозиторий. Чтобы их спрятать с остальными изменениями используется опция —include-untracked (или -u ):

Git stash list

Каждое выполнение git stash или git stash save на самом деле создает отдельный коммит и сохраняет его отдельно (в стек).

Команда git stash list выводит список всех ваших прятаний:

Самые старые «прятанья» отображаются внизу списка, самые свежие сверху. Каждое прятанье имеет идентификатор с номером, например, stash@ <0>

Git stash apply

Команда git stash apply берет самое свежее прятанье ( stash@ <0>) и применяет его к репозиторию. То есть изменения, которые находятся в этом прятанье, применяются к текущему репозиторию. Это похоже на то, как вы применяете патч, только в качестве патча выступает ваше прятанье.

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

Git stash pop

Команда git stash pop выполняет все тоже самое, что и команда git stash apply , но удаляет прятанье, которое она применяет к репозиторию.

Стало после git stash pop:

Также можно указать идентификатор прятанья:

Git stash show

Команда git stash show показывает, какие изменения содержатся в прятанье.

Показываются изменения в файлах для самого последнего прятанья (для stash@ <0>):

Чтобы показать полный diff, то есть увидеть сами изменения, используется ключ -p :

Можно указать идентификатор прятанья, чтобы вывести изменения в нем:

Git stash branch

Команда git stash branch создает новую ветку с последним прятаньем, и затем удаляет последнее прятанье (как git stash pop).

Можно также указать идентификатор прятанья:

Git stash drop

Команда git stash drop удаляет самое последнее прятанье (stash@<0>).

Можно указать идентификатор прятанья, которое нужно удалить:

Git stash clear

Команда git stash clear удаляет все прятанья. Будьте внимательные перед тем, как ее выполнять, чтобы не удалить нужные данные.

Мы рассмотрели возможные варианты использования команды git stash . Это очень полезный инструмент при работе с Git.

Добавить комментарий