| Краткий справочник по Git |
|
| Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Небольшая памятка по командам Git, приемы работы с локальным репозиторием. 1. Основные команды (выполненные в текущем каталоге корневой папки проекта):
Примечания: (1) Просмотреть все настройки можно командой git config -l или git config --list. 2. Подробная помощь по команде (откроется окно браузера со справкой): git help команда
3. Краткая подсказка по команде: git команда -h 4. Файл .gitignore позволяет создать список файлов, которые не нужно отслеживать. В этом файле можно делать комментарии, комментарием считается строка, которая начинается на символ #. В каждой строке указывается имя файла, который игнорируется, в именах можно использовать символы группирования * и ?. Чтобы исключить папку и файлы в ней, нужно добавить имя папки со слешем в конце, например: Debug/. Примеры файлов .gitignore см. в [4]. 5. Можно создавать алиасы (синонимы) команд для быстрого доступа к ним. Вот так например, можно создать синоним git st для команды git status: git config --global alias.st "status -s" После этого команды git st и git status будут выполняться одинаково. Установка выполняется по шагам с помощью обычного мастера. Однако не некоторых шагах не очевидно, какие опции выбирать. Начальные 4 шага вопросов не вызывают. Нужно согласиться с условиями лицензии, выбрать папку для установки, поставить галочки устанавливаемых компонентов, выбрать место размещения для ярлыков запуска. Можно оставить все по умолчанию:
На этом шаге лучше всего выбрать редактор, которым Вы привыкли пользоваться. Мне нравится Notepad2:
На этом шаге предлагают настроить рабочее окружения для запуска Git. Первый вариант никак не модифицирует переменные окружения, подразумевается запуск Git под управлением командной строки MinGW bash. Второй и третий вариант прописывает некоторые переменные окружения (пути запуска), чтобы можно было запускать Git как из стандартного интерпретатора команд Windows, так и из MinGW bash. Я выбрал второй вариант, который задан по умолчанию:
Здесь выбирается библиотека, с помощью которой обслуживаются защищенные соединения. Оставил этот вариант по умолчанию:
Здесь выбрал вариант, который при операциях Git не модифицирует окончания строк текстовых файлов:
Здесь лучше оставить выбор по умолчанию. Вариант настройки MinTTY обеспечивает удобную цветовую подсветку выводимого текста в консоли:
Эти опции тоже лучше оставить по умолчанию:
Как работать с Git по шагам, начиная с создания репозитория. Предполагается, что Git уже установлен. 1. Зайдите в рабочий каталог проекта, запустите сессию bash. Можно конечно пользоваться и стандартной командной строкой Windows, но MINGW64 Bash удобнее, потому что он предоставляет цветовую подсветку сообщений, и корректно поддерживает Unicode, что позволяет пользоваться русскими буквами в командах Git.
2. Необходимо создать репозиторий и указать для него имя пользователя и email. Для создания репозитория выполните команду: git init После этого выполните следующие команды (вместо Your Name и anyemail@domain.ru укажите любое имя и адрес электронной почты): git config --global user.name "Your Name" git config --global user.email "anyemail@domain.ru" 3. Выполните команду git add -n *, которая выведет список файлов, которые могут быть потенциально добавлены в репозиторий. Скорее всего, в этом списке будут некоторые файлы, изменение которых отслеживать не нужно (объектные и двоичные файлы, картинки, логи и т. п.). Если такие файлы есть, то перейдите к шагу 4, а если нужно добавить все файлы из выведенного списка, то перейдите к шагу 6. Если проект большой, и много его файлов находится в отдельных папках, то команду проверки git add -n можно запускать на файлы только одной папки. Например, вот проверка, какие файлы будут добавляться в репозиторий из папки lib проекта: git add -n lib 4. Создайте в текстовом редакторе файл .gitignore, после этого начните добавлять в него записи для тех файлов, которые нужно игнорировать (Git не будет их отслеживать). Начните с папок, которые находятся в каталоге проекта, папку .git обрабатывать не нужно, это служебная папка. Внимание: чтобы можно было в файле .gitignore использовать имена файлов с русскими буквами, файл .gitignore должен быть в кодировке UTF-8. Предположим, что есть папка bin в каталоге проекта, и в ней находятся файлы с расширениями dlb, ldr, bin, log, которые не надо добавлять в репозиторий. Тогда в файл .gitignore добавьте следующие строки: # Что игнорировать в папке bin: bin/*.dlb bin/*.ldr bin/*.bin bin/*.log Если в папке много подкаталогов, и Вы хотите обработать их сразу все, то можно воспользоваться группировкой /**/: doc/**/*.bmp Обратите внимание, что первая строка начинается на #, это просто комментарий, добавленный для удобства. Сохраните файл .gitignore и снова выполните команду git add -n *, Вы увидите, что файлы из составленного списка игнорируются. Каждую отдельную папку можно проверять командой git add -n имяпапки/. 5. После того, как создали список игнорируемых файлов для папки, добавьте её в репозиторий на отслеживание, для этого выполните команду git add без опции -n. Например, так добавляется папка lib: git add lib/ Аналогичные шаги 4 и 5 проделайте со всеми папками и файлами проекта. 6. Теперь осталось сделать коммит. git commit -m "190312 первый коммит" Здесь опция -m задает обязательный комментарий для коммита. В комментарии я люблю указывать 6 цифрами дату коммита (YYMMDD). Имейте в виду, что русские буквы в комментарии можно указывать только в командной строке bash (он устанавливается вместе с Git). 7. Чтобы сделать локальную копию репозитория в текущем каталоге на диске, используйте команду git clone. Пример клонирования репозитория BluetoothBLEClient [8] через web-ссылку: git clone https://github.com/jjjsmit/BluetoothBLEClient.git # Что игнорировать в папке bin: bin/*.dlb bin/*.ldr bin/*.bin bin/*.zlib bin/*.log # Что игнорировать в папке bootloader: bootloader/*.pcf bootloader/Debug/ bootloader/Release/ # Все содержимое в папке deleted игнорируется: deleted/ # Что игнорировать в папке doc: doc/**/*.pdf doc/**/*.png doc/**/*.bmp doc/**/*.svg doc/**/*.zip doc/**/*.jpg doc/**/*.psd doc/**/*.png doc/**/*.xls doc/**/*.doc doc/**/*.docx doc/**/*.spl7 doc/181219автовыбор-КРЛ # Что игнорировать в папке lib: lib/**/*.bak lib/**/*.old lib/**/*.pcf lib/**/*.dlb # Что игнорировать в папке mainapp-VDK: mainapp-VDK/**/*.dlb mainapp-VDK/**/*.bak mainapp-VDK/**/*.pcf mainapp-VDK/**/*.log # Что игнорировать в папке pictures: pictures/**/*.bmp pictures/**/*.png pictures/**/*.psd pictures/**/*.old pictures/**/*.bin pictures/**/*.pdf pictures/**/*.zlib # Что игнорировать в папке util: util/**/*.als util/**/*.exe util/**/*.dxe util/**/*.old util/**/*.zip util/**/*.bmp util/**/*.ico util/**/*.dll util/**/*.o util/**/*.vsd util/**/*.suo util/**/*.gz util/**/*.url util/**/*.pfx util/**/*.ldr util/**/*.chm util/calibr/Debug/ util/calibr/Release/ util/calibr/bin/Debug/ util/calibr/bin/Release/ util/calibr/obj/ util/calibr/publish/ util/zpipe-test/pack01 util/zpipe-test/src util/visa/bin/Debug/ util/visa/bin/Release/ util/visa/publish/ util/visa/obj/ [git reflog]
NAME
git-reflog - Управление информацией reflog
SYNOPSIS
git reflog < subcommand> < options>
DESCRIPTION
Эта команда принимает различные субкоманды (subcommand), а также различные опции (options), зависящие от
subcommand:
git reflog [show] [log-options] [< ref>]
git reflog expire [--expire=< time>] [--expire-unreachable=< time>]
[--rewrite] [--updateref] [--stale-fix]
[--dry-run | -n] [--verbose] [--all [--single-worktree] | < refs>...]
git reflog delete [--rewrite] [--updateref]
[--dry-run | -n] [--verbose] ref@{specifier}...
git reflog exists < ref>
Ссылка на лог (reference logs, или "reflogs") записывается, когда в локальном репозитории обновляются подсказки
по ветвям (tips of branches) и другие ссылки. Reflogs полезны в различных командах Git, чтобы можно было
указать старое значение ссылки. Например, HEAD@{2} означает "где имя HEAD использовалось за 2 перемещения
до этого", а master@{one.week.ago} означает "где имя master используется для указания на одну неделю ранее
в этом локальном репозитории", и так далее. См. в gitrevisions(7) для более подробной информации.
Эта команда управляет информацией, записанной в reflogs.
Субкоманда "show" (которая также активируется по умолчанию, когда не указана субкоманда для git reflog) покажет
лог ссылки, предоставленной в командной строке (или HEAD, по умолчанию). Команда reflog охватывает все недавние
действия, и дополнительно HEAD reflog записывает переключение между ветвями репозитория. Команда git reflog show
это алиас для команды git log -g --abbrev-commit --pretty=oneline; см. git-log(1) для дополнительной информации.
Субкоманда "expire" elfkztn старые записи журнала. Записи, которые старше чем expire time, или записи, которые
старее чем expire-unreachable time, и недоступные из текущего состояния (current tip), будут удалены из reflog.
Обычно это не используется напрямую — вместо этого см. git-gc(1).
Субкоманда "delete" удаляет одиночные записи из reflog. Её аргумент должен четко указывать на удаляемую запись
(например "git reflog delete master@{2}"). Эта субкоманда также обычно не используется напрямую.
Субкоманда "exists" проверит, subcommand есть ли в reflog ссылка ref. Если есть, то будет возвращен нулевой
статус, иначе будет возвращен ненулевой статус.
Опции для show:
git reflog принимает любые опции, которые принимает команда git log.
Опции для expire:
--all
Обработать reflogs всех ссылок.
--single-worktree
По умолчанию, когда указано --all, обрабатываются reflogs из всех рабочих ветвлений (working trees). Эта опция
ограничит обработку на reflogs только из текущего working tree.
--expire=< time>
Удалит записи, которые старше указанного времени time. Если эта опция не указана, то время устаревания
(expiration time) берется из установки конфигурации gc.reflogExpire, которая в свою очередь по умолчанию
равна 90 дней. Опция --expire=all удалит записи независимо от их возраста; --expire=never выключит удаление
доступных записей (однако см. --expire-unreachable).
--expire-unreachable=< time>
Удалит записи старее чем < time>, которые недоступны из текущего положения (current tip) ветви репозитория.
Если эта опция не указана, то expiration time берется из установки конфигурации gc.reflogExpireUnreachable,
которая в свою очередь по умолчанию равна 30 дням. Опция --expire-unreachable=all удалит недоступные
записи независимо от их возраста; --expire-unreachable=never выключит раннее удаление недоступных
записей (однако см. --expire).
--updateref
Обновит ссылку на значение верхней записи reflog (т. е. < ref>@{0}), если предыдущая верхняя запись была
удалена (эта опция игнорируется для символических ссылок).
--rewrite
Если предшествующая запись reflog была удалена, подстроит её "old" поле SHA-1 равным "new" SHA-1 полю записи,
которая ей теперь предшествует.
--stale-fix
Удалит любые записи reflog, указывающие на "испорченные фиксации" (broken commits). Испорченная фиксация
это commit, который недоступен из любого имени ссылки (reference tip), и таким образом ссылается, прямо
или косвенно, на отсутствующий commit, tree, или объект blob.
Это вычисление включает в себя обход всех доступных объектов, т. е. это имеет ту же стоимость, что и
git prune. Это главным образом предназначено для исправления повреждения, вызванного сборкой мусора
(см. git-gc) более старых версий Git, которые не защищают объекты, на которые ссылается reflogs.
-n, --dry-run
Не делает реальное удаление любых записей; просто покажет, какие записи могли быть удалены.
--verbose
Выводит дополнительную информацию.
Опции для delete:
Команда git reflog delete принимает опции --updateref, --rewrite, -n, --dry-run и --verbose, которые имеют
тоже самое значение, которое использовалось для субкоманды expire.
[git log --reflog]
--reflog
Работает так, как если бы все объекты, упомянутые в reflog, были перечислены в командной строке
как < commit>.
[Манипуляции с ветками (branch)] Ветка это просто обособленная версия проекта, которая может храниться в репозитории независимо от остальных веток. Можно переключаться между ветками, и делать в каждой из них какую-либо экспериментальную работу.
Хороший стиль работы - не плодить слишком много веток, чтобы не запутаться, либо вести подробную документацию по каждой ветке. В ветке master должен быть основной результат работы над проектом, а в ветках какие-либо мало значимые эксперименты. [FAQ] Необходимо сконфигурировать репозиторий, добавив в него имя пользователя и email. Для этого выполните следующие команды: git config --global user.name "Your Name" git config --global user.email "anyemail@domain.ru" Вместо Your Name и anyemail@domain.ru подставьте свое имя и адрес электронной почты. Создайте файл .gitignore, поместите его в корневую папку проекта (там же, где находится папка репозитория .git), и в этом файле создайте строки, обозначающие исключаемые файлы (см. выше описание работы с файлом .gitignore). Для этого используйте группировку /**/. Например, следующая запись .gitignore исключит из репозитория все файлы *.pdf, которые находятся в папке util, и во всех её подкаталогах: util/**/*.pdf Групповые подстановки можно также использовать и в командной строке Git. Файл .gitignore должен иметь кодировку UTF-8. Вместо стандартной консоли команд cmd.exe в Windows используйте командную строку MINGW64 bash (устанавливается вместе с Git). Процесс по шагам (взято из замечательной статьи [6]): 1. Сначала надо создать на сервере пустой репозиторий. Обычно это делается в HTML-интерфейсе сервера. После этого нужно запомнить Git-ссылку на этот репозиторий. Предположим, ссылка такая: http://git.netserver.ru/username/myproject.git 2. В папке локального репозитория выполнить команды: git remote add server http://git.netserver.ru/username/myproject.git Первая команда добавляет в конфигурацию репозитория новый сервер, вторая делает выгрузку репозитория на сервер. 3. Для того, чтобы команды git теперь работали с репозиторием на сетевом сервере git.netserver.ru, выполните команду: git config remote.origin.url http://git.netserver.ru/username/myproject.git Иногда надо дополнительно выполнить следующую команду, чтобы протолкнуть (push) текущую ветку репозитория (branch) на сетевой сервер, и установить его как приемник push: git push --set-upstream origin master После этой команды git push и git pull будут по умолчанию работать с репозиторием на сетевом сервере. 4. Чтобы сохранить наработанные изменения и протолкнуть их на сервер, используйте команды: git add . Чтобы засинхронизировать текущий проект с сервером, используйте команду: git pull В репозитории (это был nRF5x SDK 12.3) множество проектов примеров содержат файлы Makefile, распределенные по разным каталогам. Простая команда с указанием имени файла не позволяет добавить в репозиторий эти файлы: d:\asm\nRF5_SDK_12.3.0_d7731ad>git add Makefile
fatal: pathspec 'Makefile' did not match any files
Проблема в том, что тут указано полное имя, без шаблона wildcard. Чтобы команда сработала, нужно указать в качестве имени файла */Makefile, что будет соответствовать файлам Makefile в любом из подкаталогов репозитория: d:\asm\nRF5_SDK_12.3.0_d7731ad>git add */Makefile
add 'examples/ant/ant_advanced_burst/d52_starterkit/s212/armgcc/Makefile'
add 'examples/ant/ant_advanced_burst/pca10040/s212/armgcc/Makefile'
add 'examples/ant/ant_async_transmitter/d52_starterkit/s212/armgcc/Makefile'
add 'examples/ant/ant_async_transmitter/pca10040/s212/armgcc/Makefile'
add 'examples/ant/ant_background_scanning/d52_starterkit/s212/armgcc/Makefile'
add 'examples/ant/ant_background_scanning/pca10040/s212/armgcc/Makefile'
add 'examples/ant/ant_broadcast/rx/d52_starterkit/s212/armgcc/Makefile'
На примере файла .gitignore: git add .gitignore
Пример для добавления всех файлов, имена которых начинаются на точку: git add ".*"
Попытался сделать push ветки на сервер, не получилось, git выдает сообщение: fatal: Вы сейчас не находитесь ни на одной из веток
В чем ошибка: перед внесением изменений в код не была установлена текущая ветка. Что надо сделать: 1. Копию всех исходников! Восстановить случайно удаленный файл можно командой git checkout имяфайла. $ git status
Текущая ветка: main
Эта ветка соответствует « main ».
Изменения, которые не в индексе для коммита:
удалено: src/adcbatt.c
удалено: src/main.c
$ git checkout src/adcbatt.c
Updated 1 path from the index
$ git checkout src/main.c
Updated 1 path from the index
В чем ошибка: перед внесением изменений в код не была установлена текущая ветка. Что надо сделать: 1. Копию всех исходников! $ git config --list
$ git config --global core.editor gedit
Подобная ошибка может произойти, если была переустановка операционной системы, и каталог репозитория был восстановлен с помощью внешнего диска с файловой системой FAT32. $ git status
fatal: detected dubious ownership in repository at '/home/имяпользователя/каталог'
To add an exception for this directory, call:
git config --global --add safe.directory /home/имяпользователя/каталог
Исправить ошибку можно либо командой git config --global, как советуется в этом сообщении об ошибке, либо если поменять владельца каталога репозитория на текущего пользователя: $ sudo chown -R $USERNAME каталогрепозитория
Откат одного файла: $ git checkout -- полный/путь/до/файла Откат всех файлов сразу: $ git reset --hard
Следующие команды принудительно перезапишут локальные изменения репозитория и восстановят зафиксированное состояние из сетевого репозитория: $ git reset --hard HEAD
$ git pull
Более мягкие методы, например с помощью команды git stash, см. в посте [10]. Используйте команду git diff. Подробнее см. [12]. Предположим, что вы сделали несколько изменений в проекте, и не хотите делать фиксацию (commit) этих изменений. И вам нужно переключиться на какую-то предыдущую фиксацию, сбросив все эти изменения. Для этого нужно сначала сбросить все изменения командой git reset --hard, а потом командой git checkout переключиться на нужную фиксацию, указав её контрольную сумму (первая команда сбрасывает все текущие изменения, её выполнять необязательно): $ git reset --hard
$ git checkout 93daeff2400033f00e5adbf04fb68cab27e7f9ff
[Что произойдет при откате] После того, как вы откатились на любую предыдующую фиксацию, как в этом примере, вы получите особое состояние репозитория Git, так называемое состояние "отсоединенной головы" ('detached HEAD' state). Например (здесь 93daeff это первые несколько символов хеша одной из предыдущих фиксаций): $ git checkout 93daeff
M dependencies.lock
Note: switching to '93daeff'.
В этом сообщении Git предупреждает вас о том, что вы находитесь в особом состоянии, и объясняет, как действовать дальше: 1. "You are in 'detached HEAD' state." (Вы находитесь в состоянии «отсоединенной HEAD».) Что это значит: указатель HEAD обычно показывает на ветку (по умолчанию обычно это ветка main, но это может быть и другая ветка, если вы её создали ранее). Эта ветка, в свою очередь, показывает на последний коммит. Когда вы переключаетесь напрямую на хеш коммита (как вы сделали), HEAD перестает указывать на ветку и начинает указывать напрямую на этот конкретный коммит. Это и есть «отсоединенный HEAD». 2. "You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch." (Вы можете осматриваться, вносить экспериментальные изменения и коммитить их, а также можете отменить любые коммиты, сделанные в этом состоянии, просто переключившись обратно на ветку, не влияя на другие ветки.) Пояснение: это главный плюс такого состояния. Вы можете использовать этот коммит как "песочницу": - Посмотреть код. 3. "If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c < new-branch-name>" (Если вы хотите создать новую ветку, чтобы сохранить коммиты, которые вы создадите, вы можете сделать это сейчас или позже, используя флаг -c с командой switch. Пример: git switch -c < имя-новой-ветки>.) Пояснение: это инструкция, как сохранить ваши эксперименты. Если вы поняли, что хотите оставить изменения, которые сделали в этом состоянии, не теряйте их. Просто создайте из этого состояния новую ветку. Тогда HEAD прикрепится к этой новой ветке, и коммиты сохранятся навсегда. 4. "Or undo this operation with: git switch -" (Или отмените эту операцию с помощью: git switch -) Пояснение: Если вы просто хотели посмотреть и ничего не менять, выполните эту команду. Она вернет вас туда, где вы были до этого (на вашу предыдущую ветку), и состояние "отсоединенной HEAD" исчезнет. 5. "Turn off this advice by setting config variable advice.detachedHead to false" (Отключите это предупреждение, установив переменную конфигурации advice.detachedHead в false.) Пояснение: просто совет, как убрать это длинное сообщение в будущем, если оно вам надоест (не отключайте, пока вы новичок). [Как вернуться обратно] Выполните любую из следующих команд: git switch - Здесь имя_ветки это имя той ветки, на которой вы работали. Например, это может быть ветка main (имя ветки по умолчанию), если вы не создавали новые ветки. Цветной вывод: git reflog --date=iso Монохромный вывод: git reflog --pretty='%cd %h %gd %gs' Пользовательский формат: git reflog --format='%C(auto)%h %< |(20)%gd %C(blue)%cr%C(reset) %gs (%s)' См. также [16]. git log --graph --oneline --decorate --all См. также [17]. При переходе на новый SDK было удалено из локальной папки проекта множество файлов. После команд git add * и git commit -m "сообщение фиксации" эти файлы остались в локальном репозитории git, помеченные как "deleted". Как их быстро удалить, чтобы не удалять каждый файл по отдельности командой git rm? Это можно сделать следующей последовательностью команд: $ git add --all Что означает -all. Опция --all команды add (можно применить вместо неё -A) добавит изменения всех отслеживаемых и не отслеживаемых в базе файлов, т. е. удалит из репозитория все удаленные в проекте файлы, и добавит не отслеживаемые, в том числе и те, которые начинаются на точку (такие как .gitignore или .config) (см. [1]). Что означает -am. Из документации: "Команда git commit -a автоматически отразит в базе репозитория все отслеживаемые, модифицированные файлы перед применением фиксации. Если вы считаете, что стадия git add в рабочем процессе излишняя, Git позволит вам пропустить эту часть с помощью опции -a. Это в основном говорит Git запустить git add на любом файле, который "отслеживается" - т. е. на любом файле, который был в вашей последней фиксации, и который был изменен. Это позволит вам, если захотите, получить рабочий процесс больше похожим на стиль Subversion, когда после редактирования файлов вы просто запускаете git commit -a, когда хотите сделать снимок всего, что было изменено. Хотя вам все еще понадобится запустить команду git add, чтобы начать отслеживать новые файлы, так же как и в Subversion. Таким образом, команда git commit -am позволит вам добавить изменения в базу репозитория и одновременно создать фиксацию с указанным сообщением [2]. $ git log --date=format:"%d %B %Y" Чтобы узнать remote-ссылку репозитория через Git, используйте команду: git remote -v Эта команда покажет все настроенные удалённые репозитории (обычно `origin`) с URL для fetch и push. Пример вывода: origin https://github.com/username/repo.git (fetch) [Другие полезные команды] Показать URL только для конкретного remote (например, origin): git remote get-url origin Показать подробную информацию о remote: git remote show origin Посмотреть конфигурацию репозитория (где хранятся все remote): git config --get remote.origin.url Если нужно получить ссылку в виде переменной для скрипта: REMOTE_URL=$(git remote get-url origin) Обычно используется git remote -v, так как это наиболее информативный и простой вариант. Когда вы используете git commit -e, Git открывает текстовый редактор, чтобы вы могли написать или отредактировать сообщение коммита. Чтобы завершить ввод и создать коммит, нужно **сохранить файл с сообщением и закрыть редактор**. Способ сохранения и выхода зависит от вашего редактора: Vim / Vi: нажмите `Esc`, затем введите `:wq` и нажмите `Enter` (сохранить и выйти). После того как вы сохраните файл и закроете редактор, Git автоматически завершит коммит с вашим сообщением. Для того чтобы Git игнорировал изменения прав доступа (chmod) к файлам и папкам, нужно настроить параметр core.fileMode. Вот как это сделать: 1. Для конкретного репозитория. Находясь в папке репозитория, выполните команду: git config core.fileMode false 2. Глобально (для всех репозиториев на компьютере). Если вы хотите, чтобы Git всегда игнорировал права доступа, выполните: git config --global core.fileMode false Что это даст? - Git перестанет видеть изменения бита «исполняемости» (executable) и прав на запись/чтение. Важное предостережение: этот параметр не отключает отслеживание прав, которые уже были закоммичены. Если вы хотите, чтобы Git совсем забыл о правах для конкретного файла, нужно выполнить: git update-index --chmod=-x путь/к/файлу (или `+x` для добавления исполняемости), после чего закоммитить это изменение. Права для папок. Git не отслеживает права доступа к папкам напрямую (он отслеживает только файлы). Поэтому настройка `core.fileMode` полностью решает проблему с игнорированием прав для всего содержимого репозитория, включая папки (через их файлы). Проверка текущего значения. Чтобы узнать, включён ли игнор: git config core.fileMode Как применить на каталог с рекурсией на Windows? git ls-files ваша_папка | xargs git update-index --chmod=-x Как применить на каталог с рекурсией на Linux? Команда `git update-index` сама по себе не поддерживает рекурсивную обработку каталогов. Однако в Ubuntu это легко сделать, комбинируя её с другими командами оболочки. Ниже приведены три способа. Самый безопасный и рекомендуемый — с использованием `git ls-files`. Способ 1: `git ls-files` + `xargs` (рекомендуется) Этот метод получает список всех файлов, отслеживаемых Git, и передаёт их по очереди в `git update-index`. git ls-files -z | xargs -0 git update-index --chmod=-x ● `git ls-files -z` — выводит имена всех отслеживаемых файлов, разделяя их нулевым символом (`\0`). Это корректно обрабатывает имена с пробелами и спецсимволами. Способ 2: `find` (простой, но есть нюансы) find . -type f -exec git update-index --chmod=-x {} \; ● Эта команда рекурсивно обходит всё, начиная с текущего каталога (`.`), находит все обычные файлы (`-type f`) и для каждого из них выполняет `git update-index --chmod=-x`. Способ 3: `git add --chmod=-x` (Git 2.9 и новее) Если у вас установлен Git версии 2.9 или выше, проще всего использовать встроенную возможность `git add`: git add --chmod=-x . ● Эта команда рекурсивно обрабатывает все файлы в текущем каталоге (и подкаталогах), снимает с них флаг выполнения и сразу же добавляет изменения в индекс (staging area). Важные замечания: 1. Изменяется только индекс Git. `git update-index` (и `git add --chmod`) меняет атрибуты только в индексе (staging area). Реальные права доступа к файлам в вашей рабочей директории не меняются. Если вы хотите также изменить права в файловой системе, нужно дополнительно выполнить команду `chmod -x` для нужных файлов. 2. Только для отслеживаемых файлов. Все перечисленные команды (кроме `find`) влияют только на те файлы, которые уже находятся под версионным контролем. Новые или игнорируемые файлы не затрагиваются. 3. Проверьте результат. После выполнения любой из команд выполните `git status`, чтобы увидеть, какие изменения попали в индекс. Убедитесь, что всё соответствует вашим ожиданиям. Для этого нужно переписать историю коммитов, что является деструктивной операцией. После неё все хеши коммитов изменятся, поэтому при работе с общим репозиторием необходимо согласовать действия со всей командой. Для решения этой задачи есть два основных инструмента. Современный и рекомендуемый — git filter-repo, а git filter-branch — это классический, но устаревший способ. Способ 1: git filter-repo (рекомендуемый) Этот инструмент нужно установить отдельно (например, через `pip install git-filter-repo`), но он работает быстрее и безопаснее. Чтобы удалить файл readme.txt из всей истории, выполните команду в корне репозитория: git filter-repo --invert-paths --path readme.txt Если файл находится не в корне, укажите путь к нему, например: git filter-repo --invert-paths --path path/to/readme.txt Ключ `--invert-paths` означает, что нужно сохранить всё, кроме указанных файлов. Способ 2: git filter-branch (классический) Эта команда встроена в Git, но её использование не рекомендуется для новых проектов. Для удаления файла `readme.txt` из всей истории выполните: git filter-branch --force --index-filter \ Расшифровка опций: --index-filter — применяет команду к индексу (области подготовленных файлов) каждого коммита, что работает быстрее, чем работа с рабочим каталогом. git rm --cached --ignore-unmatch — удаляет файл из индекса, игнорируя ошибку, если файла нет в коммите. --prune-empty — удаляет коммиты, которые стали пустыми после удаления файла. --tag-name-filter cat — обновляет существующие теги. -- --all — применяет изменения ко всем веткам и тегам. [Важные шаги после переписывания истории] После выполнения любой из этих команд необходимо выполнить очистку и принудительно отправить изменения в удалённый репозиторий. 1. Очистка старых ссылок и мусора: эти команды удаляют резервные ссылки на старую историю и запускают сборщик мусора для освобождения места. git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin 2. Принудительный пуш в удалённый репозиторий: Так как история была переписана, обычный git push не сработает. Используйте принудительный пуш: git push origin --force --all [Важные предостережения] Работа в команде: после переписывания истории все ваши коллеги должны будут заново клонировать репозиторий или выполнить `git fetch --force` и сбросить свои ветки. Резервная копия: перед выполнением этих операций настоятельно рекомендуется сделать полную резервную копию всего репозитория. Локальный файл: если вы хотите удалить файл только из истории, но оставить его в рабочем каталоге, используйте `git rm --cached` перед переписыванием истории. [Альтернативный инструмент: BFG Repo-Cleaner] Существует также сторонний инструмент BFG Repo-Cleaner, который специализируется на удалении больших или конфиденциальных файлов из истории Git и может быть проще в использовании. git diff выдает сообщение: warning: in the working copy of '.gitignore', LF will be replaced by CRLF the next time Git touches it Как избавиться от этого сообщения? [Что это означает?] Предупреждение: в рабочей копии файла `.gitignore` символы окончания строк `LF` будут заменены на `CRLF` при следующем обращении Git к этому файлу. Git предупреждает, что в вашем файле `.gitignore` используются переводы строк в стиле Unix (`LF`), но ваша текущая конфигурация Git (например, `core.autocrlf` или настройки атрибутов) предписывает при следующем изменении файла автоматически преобразовывать их в формат Windows (`CRLF`). Это не ошибка, а информационное сообщение. [Как избавиться от этого сообщения?] Основные способы: 1. Самый надёжный способ – создать в корне проекта файл .gitattributes, и прописать в нём правила для всех текстовых файлов, например: * text=auto eol=lf Это заставит Git при коммитах преобразовывать все текстовые файлы к формату `LF`, и предупреждение исчезнет. Также можно явно задать правила для конкретных файлов. 2. Изменить глобальную настройку `core.autocrlf`: - На Windows: `git config --global core.autocrlf true` 3. Отключить само предупреждение (не рекомендуется): git config --global core.safecrlf false Это скроет сообщение, но не решит проблему с несовместимостью окончаний строк. Рекомендуется воспользоваться именно первым способом – он самый правильный и для индивидуальной работы, и для командной. [Почему предупреждение осталось?] git config --global core.autocrlf true После выполнения этой команды предупреждение git diff осталось. git diff Это нормально — давайте разберёмся, почему так происходит и что с этим делать. Почему предупреждение осталось? `core.autocrlf true` говорит Git: - при извлечении (checkout) превращать `LF` в `CRLF` (для Windows),| Однако это правило применяется не мгновенно ко всем файлам, а только в момент, когда Git касается файла — то есть когда вы его добавляете (`git add`), переключаете ветку или выполняете `git checkout`. Команда `git diff` как раз сравнивает рабочую копию с индексом (или с последним коммитом). Если в рабочей копии у файла `.gitignore` стоят `LF`, а Git "знает", что при следующем добавлении он превратит их в `CRLF`, то он честно предупреждает вас об этом. Сама настройка `autocrlf` не приводит к немедленной замене — она только определяет поведение при операциях записи. Как убрать это предупреждение прямо сейчас? Вам нужно дать Git возможность применить правило к этому файлу. Самый простой способ — добавить файл в индекс (даже если он не менялся): git add .gitignore После этого Git "коснётся" файла и преобразует его окончания строк согласно `autocrlf`. При следующем запуске `git diff` предупреждение исчезнет (если, конечно, вы не измените файл снова вручную, вставив новые `LF`). Если таких файлов много, можно сделать массовую «перенормализацию» всех файлов в репозитории: git add --renormalize . Эта команда заставит Git перечитать атрибуты и применить их ко всем файлам, обновив их в индексе. После этого предупреждения больше не будут появляться (пока вы не создадите новые файлы с неподходящими окончаниями). Как избавиться от предупреждения навсегда (и для всех будущих файлов)? Ваш `core.autocrlf true` уже настроен глобально — это хороший шаг. Но для полной уверенности и единообразия лучше использовать файл `.gitattributes` в корне проекта. Он имеет приоритет над глобальной настройкой и гарантирует одинаковое поведение у всех разработчиков. Создайте `.gitattributes` со следующим содержимым: * text=auto А затем выполните: git add --renormalize . После этого все файлы в репозитории получат правильные окончания, и предупреждение больше никогда не появится ни у вас, ни у коллег. Если предупреждение всё же появляется после `git add`? Проверьте, не стоит ли у вас локально переопределение через `.gitattributes` или `core.autocrlf` на уровне репозитория. Команда: git config --local --list | grep autocrlf .. покажет, какие правила действуют для этого конкретного файла. Возможно, вы ранее установили `core.autocrlf false` локально — тогда глобальная настройка не применяется. Резюме: - Предупреждение при `git diff` — это нормально, оно говорит о том, что Git планирует преобразование при следующем касании. Чтобы проверить, чем ваш локальный репозиторий отличается от удаленного (сетевого), нужно выполнить два действия: забрать свежие данные из сети (но не сливать их) и сравнить ветки. Вот пошаговая инструкция: 1. Забрать изменения без слияния (fetch). Эта команда скачивает все новые данные из интернета, но не трогает ваши локальные файлы и не сливает ветки. git fetch --all Флаг --all обновляет информацию сразу обо всех удаленных репозиториях (обычно это origin). 2. Проверить разницу (статус и сравнение). Теперь у вас есть актуальная информация о том, что есть в сети. Используйте одну из команд ниже. А. Быстрый статус (только «впереди» или «позади»). Позволяет узнать, сколько коммитов вам нужно скачать (pull) и сколько вы уже готовы отправить (push): git status Вы увидите что-то вроде: Your branch is ahead of 'origin/main' by 2 commits. (вы впереди на 2 коммита — надо сделать push) Б. Подробный список изменений (что именно изменилось). Чтобы увидеть конкретные файлы и строки кода, которые отличаются: git log HEAD..origin/main --stat Этот пример команды покажет, что нового появилось в удаленной ветке main по сравнению с вашей локальной. Или универсальная команда для просмотра разницы в обе стороны: git log --oneline --graph --all --decorate Она покажет красивую картинку всех веток (локальных и удаленных), и вы визуально увидите, где разошлись пути. Визуальный способ (если лень читать логи). Выполните эту команду, чтобы увидеть изменения в виде компактного списка: git log --left-right --oneline origin/main...HEAD Эта команда покажет коммиты, которые есть только у вас (помечены < ), и коммиты, которые есть только в сети (помечены >). Важно понимать отличия отличие fetch от pull: git fetch — просто смотрит, что изменилось (безопасно). git pull — скачивает и сразу сливает изменения в ваши файлы. Не используйте pull, если вы хотите только проверить статус, иначе могут возникнуть конфликты, которые придется срочно решать. Самый быстрый однострочник. Если вы хотите одной командой обновить информацию и тут же увидеть, впереди вы или позади: git fetch && git status [Pro Git] Существует книга, которая может послужить замечательным введением в мир git - Pro Git, авторы Scott Chacon и Ben Straub. Эта книга переведена на многие языки, в том числе и на русский язык. Книга на русском языке доступна в виде репозитория GitHub [13], а также доступна её онлайн-версия [14]. Получить книгу последней версии в популярных электронных форматах можно, если выполнить её компиляцию (см. врезку). $ git clone https://github.com/progit/progit2-ru.git
$ cd progit2-ru/
$ bundle config set --local path '.bundle/vendor'
$ bundle install
$ bundle exec rake book:build
После выполнения этой команды в папке проекта progit2-ru появятся скомпилированные файлы progit.pdf, progit.mobi, progit-kf8.epub, progit.fb2.zip, progit.epub, progit.html. При выполнении команды bundle install столкнулся с ошибкой: Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
current directory:
/home/user/asm/progit2-ru/.bundle/vendor/ruby/3.0.0/gems/racc-1.7.3/ext/racc/cparse
/usr/bin/ruby3.0 -I /usr/lib/ruby/vendor_ruby -r ./siteconf20240109-25035-tgyk07.rb extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib/ruby/include/ruby.h
You might have to install separate package for the ruby development
environment, ruby-dev or ruby-devel for example.
extconf failed, exit code 1
Как исправить: $ sudo apt install ruby-bundler
[git status: проблема с изменениями прав доступа к файлам] Часто происходит неприятная ситуация с большим репозиторием, когда git status показывает изменения почти во всех файлах, хотя на самом деле изменены были только права доступа: $ git diff components/unity/port/esp/unity_utils_memory_esp.c
diff --git a/components/unity/port/esp/unity_utils_memory_esp.c
b/components/unity/port/esp/unity_utils_memory_esp.c
old mode 100644
new mode 100755
В Ubuntu режим файлов 100644 устанавливается через файловую систему, а не настройками Git. Этот код (644) — это стандартные разрешения для обычных файлов в Linux, которые Git просто сохраняет в своей базе. Ниже приведены способы управления разрешениями файлов, в том числе для получения режима 644. Чтобы изменить разрешения файла в файловой системе Ubuntu на 644 (владелец: чтение+запись, остальные: только чтение), используется команда chmod: $ chmod 644 имя_файла
То же самое с рекурсией по директориям: $ chmod -R 644 имя_файла
Альтернативный способ рекурсивного изменения прав доступа: $ find . -type f -exec chmod -x {} \;
Чтобы проверить текущие разрешения файла: $ ls -l имя_файла
В результате вы увидите строку -rw-r--r--, которая и соответствует разрешениям 644. Разрешения и Git: ● Автоматическое отслеживание: когда вы добавляете файл с разрешениями 644 в репозиторий с помощью git add, Git запомнит их как режим 100644 в своем индексе. Ключевые различия: система vs Git:
Если Git постоянно отмечает изменение режима файла (например, с 100755 на 100644), это может быть связано с настройкой core.filemode или работой с файлами между разными ОС. Чтобы игнорировать изменения только в разрешениях файлов, можно установить опцию конфигурации core.filemode false в вашем репозитории: $ git config core.filemode false
[Словарик] branch ветвление проекта (создание его отдельной версии в репозитории). commit легковесный снимок состояния файлов в определенный момент времени (когда был сделан коммит). head самая последняя версия файлов в репозитории. repository репозиторий, база данных, где хранится история изменений проекта. Git хранит репозиторий в папке .git, которая находится в корневом каталоге проекта. staging area область файловой системы (список файлов), подготовленная к коммиту. stash операция, которая поглощает грязное состояние рабочего каталога, то есть изменённые отслеживаемые файлы и изменения в индексе, и сохраняет их в стек незавершённых изменений, которые вы потом в любое время можете снова применить. [Ссылки] 1. Downloads Git site:git-scm.com. |