git
Основная используемая система управления версиями. Сейчас я ещё больше уверена, что текстопишущим людям что-то такое практически необходимо, даже если они об этом не знают и всего такого боятся. Как обычно в этом садике - случайные заметки, тыренное. В надежде на упорядочивание со временем.
(вторая используемая иногда - fossil)
Странички
- git для пишущих
- gitignore
- flashbake
- git в emacs
- ссылки про git
- myrepos - штука для автопинания многих репозиториев разом. В принципе, может не только git, но git ей родной.
Мелкие памятки себе
В консоли кириллица отображается как \цифры
git config core.quotepath false
Только один файл из другой ветки
git checkout master -- path/name.ext
или
git restore --source master -- path/name.ext
https://stackoverflow.com/questions/2364147/how-to-get-just-one-file-from-another-branch - там есть ещё варианты.
Коммит не в ту ветку, что делать?!
git reset HEAD~ --soft # вернулись к предыдущему коммиту, но не удаляем изменения git add . # изменения застейджили git stash # сохранили застейдженное в stash git checkout имя-верной-ветки # переключились куда надо git stash pop # извлекли сохранённое из stash
На этом месте могут образоваться конфликты слияния, которые надо решить до следующего шага. Не совсем автоматическая процедура.
git add . # застейджили уже здесь git commit -m "описание коммита" # закоммитили на нужное место
Сбросить изменения к последнему закоммиченному
git reset --hard HEAD
В отдельном файле:
git checkout путь/имяфайла
И если это новые файлы, которые не были даже добавлены:
git clean -i -d
- -d - чтоб заглядывал в неотслеживаемые каталоги.
- как вариант, можно использовать -n для того, чтоб посмотреть, что будет вычищено, и -f - чтоб таки сделать это.)
- в –help можно прочитать ещё потенциально полезного. Например, -X позволяет убрать файлы, которые git игнорирует.
Срочно подправить ошибку, замеченную до пуша
git commit -a --amend --no-edit
Довнести все изменения, сообщение коммита не менять
Или
git reset --soft HEAD~
Сделать вид, что коммита не было, сохранить состояние файлов. Можно теперь закоммитить как надо.
detached head
If you want to delete your changes associated with the detached HEAD You only need to checkout the branch you were on, e.g.
git checkout master
Next time you have changed a file and want to restore it to the state it is in the index, don't delete the file first, just do
git checkout -- path/to/foo
This will restore the file foo to the state it is in the index.
If you want to keep your changes associated with the detached HEAD
git branch tmp # this will save your changes in a new branch called tmp. Очевидимо, вместо tmp можно любое другое название git checkout master
If you would like to incorporate the changes you made into master, run git merge tmp
from the master branch. You should be on the master branch after running git checkout master
.
Добавить удалённый (remote) репозиторий уже существующему локальному
Например
git remote add origin git@gitlab.com:agnessa/emacs-config.git
«git@gitlab.com:agnessa/emacs-config.git» - очевидимо, конкретный удалённый реп.
Про удалённые (deleted) файлы
https://stackoverflow.com/questions/6017987/how-can-i-list-all-the-deleted-files-in-a-git-repository
git log --diff-filter=D --summary
Краше
git log --all --pretty=format: --name-only --diff-filter=D | sort -u
This will get you a list of all files that were deleted in all branches, sorted by their path:
git log --diff-filter=D --summary | grep "delete mode 100" | cut -c 21- | sort > deleted.txt
Локальные настройки имени и адреса
Если в разных репозиториях нужно коммиты от разных Name+email.
git config --local user.name "Name" git config --local user.email email@mysite.ru
Или залезть в .git/config репозитория и написать
[user] email = name@mysite.ru name = Name
Проверка настроек
Если хотите проверить используемую конфигурацию, можно использовать команду git config –list, чтобы показать все настройки, которые Git найдёт:
$ git config --list user.name=John Doe user.email=johndoe@example.com color.status=auto color.branch=auto color.interactive=auto color.diff=auto
Некоторые ключи (названия) настроек могут отображаться несколько раз, потому что Git читает настройки из разных файлов (например, из /etc/gitconfig
и ~/.gitconfig
). В таком случае Git использует последнее значение для каждого ключа.
Также вы можете проверить значение конкретного ключа, выполнив git config <key>:
$ git config user.name John Doe
Так как Git читает значение настроек из нескольких файлов, возможна ситуация когда Git использует не то значение что вы ожидали. В таком случае вы можете спросить Git об origin этого значения. Git выведет имя файла, из которого значение для настройки было взято последним:
$ git config --show-origin rerere.autoUpdate file:/home/johndoe/.gitconfig false
Настройка ключа для конкретного сервиса
Пишется в ~/.ssh/config
.
Host shortname HostName that.address.name User username IdentityFile ~/.ssh/key_for_service PreferredAuthentications publickey IdentitiesOnly yes
Посмотреть историю изменений одного файла
git log -p -- path/filename.txt
Найти коммиты с появлением и удалением строки
В кавычках, разумеется, строка
git log -S '7b28ff06-ab13-4070-8dc2-fcbc9fe2f0b0'
- this looks for differences that introduce or remove an instance of <string>. It usually means "revisions where you added or removed line with 'Foo'".
the –pickaxe-regex option allows you to use extended POSIX regex instead of searching for a string. Example (from git log): git log -S"frotz\(nitfol" –pickaxe-regex
С регэкспом
git log -G<regexp> --branches --al
https://stackoverflow.com/questions/2928584/how-to-grep-search-committed-code-in-the-git-history
И без учёта регистра
git log -S foobar -i --oneline
or
git log --regexp-ignore-case -Sfoobar
or
git log -i -Sfoobar
Note that with 1.x git versions this option will not work with a regexps, only with a fixed string. It works with regexps only since git 2.0 and commit 218c45a, git 2.0, May 2014.
https://stackoverflow.com/questions/25384842/case-insensitive-git-pickaxe-search
Достать файл из коммита
git checkout b9d55fe7e7e48b106464dfad0285190ced2c78ea /path/to/filename
- после слова checkout и перед путём - хэш подходящего коммита. вместо хэша можно указывать по истории, типа там сколько назад от HEAD и типа того.
- путь к файлу - от корня репозитория
"git stripspace" - может убирать комментарии и ненужные пробелы
Не удаляет пробелы, используемые в качестве отступов. Добавляет заключительный перенос строки в конце файла, если его нет.
Дата последнего изменения файла
git log -1 --pretty="format:%ci" /path/to/repo/anyfile.any
-1 restricts it to the very last time the file changed
%ci is just one of the date formats you can choose from others here at https://git-scm.com/docs/pretty-formats
https://stackoverflow.com/questions/22497597/get-the-last-modification-date-of-a-file-in-git-repo
Пуш не пушится
error: src refspec <branchname> соответствует более чем одному error: не удалось отправить некоторые ссылки в «<репозиторий>»
или
error: src refspec <branchname> matches more than one error: failed to push some refs to '<repository>'
Гит не может понять, что конкретно я от него хочу. Что именно отправить-то надо. Вероятнее всего, почему-то образовался тег, совпадающий с именем ветки. Можно подробнее указать ветку (refs/heads/<branchname>
), можно удалить тег.
Удалить тег:
git tag -d <tag>
Переименовать тег не судьба вообще. :)
Если хочется полно обратиться к тегу, это refs/tags/<tag>
.
Полностью команда push - это
git push [options] <repository> <refspec>
, где refspec
- это
<source>:<destination>
Обычно это ветки, но могут быть и теги. И теоретически можно завести ещё пространство имён под refs
, но я пока понятия не имею, зачем это могло бы быть нужно.
pushurl – или пушить в несколько репозиториев разом
You can choose to provide the name of a remote which you had previously configured using git-remote, git-config or even by a manual edit to the $GIT_DIR/config file. The URL of this remote will be used to access the repository. The refspec of this remote will be used by default when you do not provide a refspec on the command line. The entry in the config file would appear like this:
[remote "<name>"] url = <URL> pushurl = <pushurl> push = <refspec> fetch = <refspec>
The <pushurl> is used for pushes only. It is optional and defaults to <URL>. Pushing to a remote affects all defined pushurls or all defined urls if no pushurls are defined. Fetch, however, will only fetch from the first defined url if multiple urls are defined.
Так вот, если этих пушурлов будет несколько в одном таком remote, то git push remote будет пушить по всем. Если remote – origin, так просто git push будет пушить по всем.
Источник – man git-push. Упоминание, что так бывает – в емаксочатике. :)
репозиторий отказал в соединении по ключу
Недавно всё ещё работало, и вдруг внезапно отказывает в соединении.
При запросе ssh -vT git@example.server.name
получается много всего вроде бы ок, в конце:
debug1: send_pubkey_test: no mutual signature algorithm
debug1: No more authentication methods to try.
git@example.server.name: Permission denied (publickey).
Вероятно, обновили ssh на версию, которая перестала по умолчанию признавать некоторый тип ключей. По нынешним временам это ssh-rsa. Так что надо включить их поддержку в конфиге или в конкретной команде:
PubkeyAcceptedKeyTypes +ssh-rsa
ssh -o 'PubkeyAcceptedKeyTypes +ssh-rsa' example.server.name
И всё станет ок. По крайней мере, можно воспользоваться этим, чтобы загрузить более надёжный ключ. ssh
Куда писать инфу - почему не только и не столько в описание коммита
Написать тест, который будет контролировать появление новых подобных ошибок в проекте. При настроенном CI - это мощнейший инструмент для будущих участников проекта.
Если у вас появляется желание написать целую историю в сообщении к коммиту, вам следует подумать, как можно предоставить эту историю другим путем - тесты или документация намного лучше.
https://www.nikialeksey.com/2019/10/26/long-commit-message.html
Special GitLab References
GFM [gitlab flavored markdown] recognized special references.
You can easily reference e.g. an issue, a commit, a team member or even the whole team within a project.
GFM will turn that reference into a link so you can navigate between them easily.
GFM will recognize the following:
@foo : for specific team members or groups @all : for the whole team #123 : for issues !123 : for merge requests $123 : for snippets 1234567 : for commits [file](path/to/file) : for file references
GFM also recognizes references to commits, issues, and merge requests in other projects:
namespace/project#123 : for issues namespace/project!123 : for merge requests namespace/project@1234567 : for commits
Stash
Если кто-то еще не пользуется git stash, советую обратить на эту команду пристальное внимание. Более чем удобно, занимаясь одним делом, «отложить» текущую работу в сторону и отвлечься, скажем, на срочное исправление бага, даже если он находится в другом бранче. После исправления и коммита можно преспокойно вернуться к начатому.
i. hack-hack-hack ii. git stash iii. fix-fix-fix iv. git commit -a -m 'bugfix #31337' v. git stash pop
Те же, кто знает про git stash, посмотрите на последнюю строку — её отличие от apply в том, что откладываемые результаты не остаются во временном хранилище (посмотрите git stash list после нескольких примений stash!)
Если изменение было фактически законченным, можно оформить коммит не отходят от кассы — git stash save 'commit msg'
%Интерактивное добавление файла в индекс с выбором отдельных чанков (частный случай -i)
git add -p #
Проверка «здоровья» репозитория и удаление из него мусора.
- git fsck. Даже без –full неплохая проверка.
- git count-objects. Проверка, сколько объектов будет потеряно и объём освобождаемого места при перепаковке репозитория.
- git gc. Переупаковка локальных репозиториев и другие виды повседневных задач.
(git fsck –full — Все объекты, на которые никто не указывает.)
Настройки при клонировании
После клонирования хранилища команды git push или git pull автоматически отправляют и получают его по первоначальному адресу. Каким образом Git это делает? Секрет кроется в настройках, заданных при создании клона. Давайте взглянем:
git config --list
Опция remote.origin.url задает исходный адрес; origin — имя первоначального хранилища. Как и имя ветки master, это соглашение. Мы можем изменить или удалить это сокращённое имя, но как правило, нет причин для этого.
Если оригинальное хранилище переехало, можно обновить его адрес командой
git config remote.origin.url git://новый.url/proj.git
Опция branch.master.merge задает удаленную ветку по умолчанию для git pull. В ходе первоначального клонирования она устанавливается на текущую ветку исходного хранилища, так что даже если HEAD исходного хранилища впоследствии переместится на другую ветку, pull будет верно следовать изначальной ветке.
Этот параметр обращается только к хранилищу, которое мы изначально клонировали и которое записано в параметре branch.master.remote. При выполнении pull из других хранилищ мы должны указать нужную ветку:
git pull git://пример.com/other.git master
Это объясняет, почему некоторые из наших предыдущих примеров push и pull не имели аргументов.
git clone ssh:user@host:port/path
.git/config для i2p
You have local tunnels set up as per the guide for pull.git.repo.i2p on port 9450 and push.git.repo.i2p on port 9451
You are linking the local Git repository to the hosted repository test.git. If the hosted repository is a fork, replace "test.git" with "base/fork.git" etc.
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = git://127.0.0.1:9450/test.git pushurl = ssh://username@127.0.0.1:9451/srv/git/test.git fetch = +refs/heads/*:refs/remotes/origin/*
vcsh (для хранения конфигов)
http://vcs-home.branchable.com/ - vcsh - способ хранить в git конфиги домашней папки так, что можно два соседних файла держать в разных репозиториях.
While it may appear that there's an overwhelming amount of documentation and while the explanation of the concepts behind vcsh needs to touch a few gory details of git internals, getting started with vcsh is extremely simple.
Let's say you want to version control your vim configuration:
vcsh init vim vcsh vim add ~/.vimrc ~/.vim vcsh vim commit -m 'Initial commit of my Vim configuration' # optionally push your files to a remote vcsh vim remote add origin <remote> vcsh vim push -u origin master # from now on you can push additional commits like this vcsh vim push
If all that looks a lot like standard git, that's no coincidence; it's a design feature.
bup - backup system based on the git packfile format
Backup system based on the git packfile format, providing fast incremental saves and global deduplication (among and within files, including virtual machine images). Current release is 0.26, and the development branch is master.
- https://bup.github.io/ , 2022-07-29
- https://github.com/bup/bup. На сейчас (2022-07-29) 0.32.
- http://git-annex.branchable.com/special_remotes/bup/