Или в чём разница между git pull и git fetch? Если совсем коротко, то:
git pull = git fetch + git merge
fetch
всего лишь получает изменения с удалённого сервера никак не изменяя локальные ветки.
pull
вливает эти изменения в текущую ветку по возможности методом "быстрой перемотки" (fast forward).
Например, из feature в master:
git checkout master
git merge feature
И удалить более ненужную ветку feature (опционально):
git branch -d feature
git update-index --assume-unchanged settings.ini
Отменить игнорирование предыдущей коммандой:
git update-index --no-assume-unchanged settings.ini
Извлечь из запрятанного и удалить оттуда:
git stash pop <commit hash>
Извлечь из запрятанного, но без удаления:
git stash apply <commit hash>
Если нужен последний элемент, <commit hash>
можно не указывать.
Например, в последних пяти:
git rebase -i HEAD~5
Список команд:
- p или pick - использовать коммит
- r или reword - использовать коммит, но изменить текст сообщения
- e или edit - использовать коммит, но приостановить для его изменения
- s или squash - использовать коммит, но объединить его с предыдущим
- f или fixup - то же что "squash", но отбрасывает сообщение коммита
- x или exec - выполняет команду через командную оболочку (shell)
- d или drop - отбросить коммит (удалить)
Также можно переупорядочивать коммиты.
Пример: объединим несколько коммитов в один:
pick e51ad80 Clean mess
squash 91d085c Move text constants to methods
squash 0ec8451 Replace _L macros to _LIT
squash c394739 Move code from MainL to CListener
squash 305d2c6 Main class rename
squash c614bc5 Add g prefix for globar variable
squash 20f7919 Fix
squash 0d824e5 Add TRAP_IGNORE macros
Здесь команда pick
оставляет первый коммит в качестве базового, а squash
объединяет остальные с первым.
git reset --hard 89f6600
Здесь 89f6600 - это хеш коммита, после которого идут ошибочные коммиты.
Если нужно убрать только самый последний, то можно записать короче:
git reset --hard HEAD^
Создание простой (легковесной) метки:
git tag v5.6.7
Создание аннотированной метки:
git tag -a v5.6.7
Удаление метки:
- локальной:
git tag -d v5.6.7
- на сервере:
git push origin :refs/tags/v5.6.7
Перенос существующей метки на другой коммит (например, текущий) выполняется с флагом -f
:
git tag -f v1.4
Просмотреть список всех тегов:
git tag -l
Отправить вместе с коммитами ещё и метки:
git push --follow-tags
Отправить в удалённый репозиторий только определённую метку:
git push origin <tag name>
Начиная с Git 2.4 появилась возможность задать автоматическую отправку меток в настройках .gitconfig
:
git config --global push.followTags true
Другой вариант - вручную добавить в файл .gitconfig
строки:
[push]
followTags = true
Примечание: Автоматически git отправляет только аннотированные метки, пропуская легковесные. Рекомендуется аннотированными метками отмечать релизы, а легковесные использовать только в локальном репозитории. (Подробности тут)
git checkout -- myfile.txt
Подтянуть последние изменения из ветки master в feature. Другими словами, нужно переместить feature на конец master:
git checkout feature
git rebase master
Допустим, что возникла ситуация, когда после внесения некоторых изменений в проект, что-то сломалось и нужно найти этот "бракованный" коммит. Включаем bisect:
git bisect start
Затем указываем плохой и хороший коммиты:
git bisect bad 71fefda
git bisect good fd62f67
Псле этого git будет циклически переключать коммиты между этими двумя. Проверяем, если проблема сохраняется, вводим:
git bisect bad
А если нет, то:
git bisect good
Таким образом рано или поздно будет найдет виновный коммит:
67c1fee5c245619df28a963cdb829d8911d891ad is the first bad commit
commit 67c1fee5c245619df28a963cdb829d8911d891ad
Author: artem78 <[email protected]>
Date: Tue Mar 31 19:32:50 2020 +0300
Downloading tiles from OSM dafault layer
:040000 040000 99d4b7ff504abdcf10fdeb6ab5975f9ae5907ae6 75c522f62958fe3c0efb69069751d088cd7bcea8 M group
:040000 040000 45a8bd89290124fd156aa76963ee2068422eecaf b53d023173d23d40766ee100366dc92ac3378d05 M inc
:040000 040000 cb7d95e196d71d57264e3ed2f944e79197ded386 c8b06f81b93ab54bfd2d182b5599ec7035795da2 M src
В заключение, чтобы завершить работу команды bisect и вернуться к исходному состоянию вводим:
git bisect reset
git branch -m old_branch new_branch
Из ветки A в ветку B:
git checkout B
git cherry-pick A
git checkout A
git reset --hard HEAD^
git submodule add [email protected]:url_to/awesome_submodule.git path_to_awesome_submodule
Например, у меня возникла такая ситуация - существуют два проекта с частично общей кодовой базой (в таком случае более логично было бы использовать подмодули, но мы сейчас не об этом). В первом проекте были внесены изменеия, которые также нужно внести и во второй репозиторий. Что же делать? На помощь нам приходят патчи.
В первом репозитории на базе существующего коммита создаём патч командой:
git format-patch -1 <commit hash>
Или, если это самый последний коммит, то:
git format-patch -1
После выполнения команды, должен появиться файл с подобным названием:
0001-Fix-leaving-methods-in-destructor-E32USER-CBase-66-p.patch
Затем копируем его во второй репозиторий и выполняем:
git apply my-patch.patch
или:
git am --signoff < my-patch.patch
git shortlog
Результат выполнения команды
$ git shortlog
0017031 (1):
Enhance pluginsAdmin.h
A-R-C-A (10):
Fixed crash issue due to unsigned variable
Enhancement: add conflict detection to Shortcut Mapper
Improved Single Line Comment
Added more Change Case variants
Add commands for moving the current file tab Forward/Backward
Added new Option: Enable scrolling beyond last line
Add Scroll Tab Bar with mouse wheel capacity
Improve tab alignment in Shortcut Mapper
Make margins dpi aware
Make Task List dpi aware
Ach3r0n (1):
translationsd: update dutch localization (closes #537)
Acheron (1):
Update dutch.xml
Adam Stachowicz (1):
Polish translation: Ampersand fix
:
git shortlog -s -e -n
Результат выполнения команды
$ git shortlog -s -e -n
1144 Don Ho <[email protected]>
640 Don HO <[email protected]>
358 donho <donho@f5eea248-9336-0410-98b8-ebc06183d4e3>
83 harrybharry <harrybharry@f5eea248-9336-0410-98b8-ebc06183d4e3>
79 dail8859 <[email protected]>
67 SinghRajenM <[email protected]>
57 Christian Grasser <[email protected]>
56 Rajendra Singh <[email protected]>
49 Andreas Jönsson <[email protected]>
36 Damien GERARD <[email protected]>
30 Scott Sumner <[email protected]>
Здесь флаг -n
отвечает за сортировку кол-ва коммитов по убыванию.
Может возникнуть ситуация, когда один и тот же человек сделал коммиты под разными именами, но с одинаковым адресом электронной почты. В этом случае вывод команлы shortlog
будет похож на этот:
$ git shortlog -s -e
5 John Doe <[email protected]>
12 John D. <[email protected]>
27 jonny <[email protected]>
Чтобы сгруппировать коммиты с одинаковым email-ом под одним автором нужно в корне репозитория (т.е. там, где находится папка .git
) создать текстовый файл с именем .mailmap
и содержимым:
Your Name <[email protected]>
Для примера выше он будет выглядеть так:
John Doe <[email protected]>
Теперь вывод комманды shortlog
будет следующий:
$ git shortlog -s -e
44 John Doe <[email protected]>
Замечание: правила, заданые в файле .mailmap
не изменяют содержимое или историю коммитов и влияют исключительно на вывод команды shortlog
.
Не все люди дружат с Гитом или ГитХабом и поэтому присылают свои изменения в виде отредактированных файлов ко мне на электронную почту. Я делаю коммит как обычно, а затем изменяю автора последнего коммита. Кроме того, письмо могло пролежать непрочитанным несколько суток, поэтому я, как правило, также меняю и дату создания коммита.
git commit --amend --no-edit --date="Sun, 17 Apr 2022 21:06:27 +0300" --author="John Doe <[email protected]>"
Если вместо определённой даты нужно выставить текущую, то используем ключ --date=now
.
Проверить можно следующим образом:
git log --pretty=fuller --max-count=1
commit 6264607de6053fa9b24a2c269fe2d93038bb01fa
Author: John Doe <[email protected]>
AuthorDate: Sun Apr 17 21:06:27 2022 +0300
Commit: artem78 <********@ya.ru>
CommitDate: Mon Apr 18 21:11:16 2022 +0300
[Localization] Update Polish translation