| Краткий справочник по 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 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 планирует преобразование при следующем касании. [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. |