====== githowto.com ====== ===== Первоначальная настройка ===== # Кто автор коммитов в этом экземпляре гита - имя и адрес git config --global user.name "Your Name" git config --global user.email "your_email@whatever.com" # Задать main веткой по умолчанию git config --global init.defaultBranch main # Корректно обрабатывать окончания строк (для Windows) git config --global core.autocrlf true git config --global core.safecrlf warn ===== Создание проекта ===== # Создать новый репозиторий (можно уже после создания файлов проекта в каталоге) git init # создастся подкаталог .git # Добавить файл и закоммитить с комментарием git add hello.html git commit -m "Initial Commit" # Проверить состояние репозитория git status On branch main # Сейчас на ветке main nothing to commit, working tree clean # Нет файлов, ожидающих записи, репозиторий равен текущему состоянию каталога # Переименовать master в main, если гит старый и команда, делающая ветку main основной, не сработала git branch -m master main ===== Внесение изменений ===== # Если что-то добавить в файл и посмотреть состояние репозитория: git status On branch main Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: hello.html no changes added to commit (use "git add" and/or "git commit -a") # Можно откатить файл обратно git restore hello.html # А можно добавить его в коммит (проиндексировать) git add hello.html # После добавления статус показывает, что файл проиндексирован git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) modified: hello.html # Можно откатить индексацию (файл вернётся к добавленному, но не индексированному состоянию) git restore --staged hello.html # Отдельный шаг индексации позволяет разделять добавленные файлы на разные коммиты, # чтобы не связанные между собой изменения не попадали в один коммит. # К примеру, изменены 3 файла - a.html, b.html и c.html, и файл c.html не связан с другими. git add a.html git add b.html git commit -m "Changes for a and b" git add c.html git commit -m "Unrelated change to c" ===== Коммит ===== Если не задать параметр -m для git commit, то откроется редактор. Он задаётся в одной из настроек * переменная среды GIT_EDITOR * параметр конфигурации core.editor * переменная среды VISUAL * переменная среды EDITOR git config --global core.editor emacs # emacs git config --global core.editor "code --wait" # VSCode Гит фокусируется на изменениях в файле, а не на самом файле. К примеру, если одно изменение в файле было проиндексировано, а второе - нет, то при коммите добавится только проиндексированное изменение. Второе нужно будет сначала проиндексировать и потом коммитить. ===== История проекта ===== git log git log commit 204912e8c6cf87c0743ffa5646f4c7438d6ebeaa (HEAD -> main) Author: Your Name Date: Tue Jan 21 16:26:12 2025 +0300 Added HTML header commit 88622c4f43f5caa7a891542f09564c68fc362682 Author: Your Name Date: Tue Jan 21 16:15:07 2025 +0300 Added H1 tag commit 1a3a27e686a3baeec77a9f44a65471b88495a3e1 Author: unknown Date: Tue Jan 21 15:17:07 2025 +0300 Initial Commit # Вид настраивается, например, однострочный вид git log --pretty=oneline 204912e8c6cf87c0743ffa5646f4c7438d6ebeaa (HEAD -> main) Added HTML header 88622c4f43f5caa7a891542f09564c68fc362682 Added H1 tag 1a3a27e686a3baeec77a9f44a65471b88495a3e1 Initial Commit # Ещё варианты git log --oneline --max-count=2 # 2 последних коммита git log --oneline --since="5 minutes ago" # за последние 5 минут git log --oneline --until="5 minutes ago" # кроме последних 5 минут git log --oneline --author="Your Name" # фильтр по автору git log --all --pretty=format:"%h %cd %s (%an)" --since="7 days ago" # Укороченный хэш, время, коммент, автор 204912e Tue Jan 21 16:26:12 2025 +0300 Added HTML header (Your Name) 88622c4 Tue Jan 21 16:15:07 2025 +0300 Added H1 tag (Your Name) 1a3a27e Tue Jan 21 15:17:07 2025 +0300 Initial Commit (unknown) git log --pretty=format:"%h %ad | %s%d [%an]" --date=short # Ещё вариант 204912e 2025-01-21 | Added HTML header (HEAD -> main) [Your Name] 88622c4 2025-01-21 | Added H1 tag [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] # Сделать последний вариант pretty format по умолчанию git config --global format.pretty '%h %ad | %s%d [%an]' git config --global log.date short https://git-scm.com/docs/git-log ===== Откат на старые версии ===== # Откатиться на самый первый коммит (достаточно первых 7 символов хэша как указатель) git checkout 1a3a27e Note: switching to '1a3a27e'. You are in 'detached HEAD' state. 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. 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 Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 1a3a27e Initial Commit # hello.html выглядит как в самом начале cat .\hello.html Hello, World # Вернуться на последнюю версию в ветке main git switch main # hello.html теперь опять со всеми изменениями cat .\hello.html

Hello, World!

===== Создание тэгов версий ===== Работать с хэшами коммитов неудобно. Можно задать человеческий тэг, тогда можно будет сослаться на него. git tag v1 # задать тэг текущей версии git log -n 1 204912e 2025-01-21 | Added HTML header (HEAD -> main, tag: v1) [Your Name] ### Задать тэг предыдущей версии # Переключиться на предыдущую версию git checkout v1^ # или git checkout v1~1 git tag v1-beta git log -n 1 88622c4 2025-01-21 | Added H1 tag (HEAD, tag: v1-beta) [Your Name] # Теперь можно переключаться по тэгам git checkout v1 Previous HEAD position was 88622c4 Added H1 tag HEAD is now at 204912e Added HTML header git checkout v1-beta Previous HEAD position was 204912e Added HTML header HEAD is now at 88622c4 Added H1 tag # Список тэгов git tag v1 v1-beta # Тэги в логе git log main --all 204912e 2025-01-21 | Added HTML header (tag: v1, main) [Your Name] 88622c4 2025-01-21 | Added H1 tag (HEAD, tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] ===== Отмена локальных изменений ===== ==== До индексации ==== Чтобы откатить изменения в файле, ещё не добавленном в коммит: # Вот есть изменения, которые надо отменить git status On branch main Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: hello.html no changes added to commit (use "git add" and/or "git commit -a") # Откатить изменения git restore hello.html # Теперь чисто, изменений нет git status On branch main nothing to commit, working tree clean ==== После индексации ==== Отмена изменений в файле, добавленном в коммит git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) modified: hello.html # Убрать файл из индекса (коммита). Файл при этом остался изменённым! git restore --staged hello.html # Дальше действовать как до индексации git restore hello.html ===== Отмена коммитов ===== Есть несколько способов откатить кривой коммит. ==== Новый коммит, отменяющий предыдущий ==== ''revert'' - история коммитов сохраняется: есть и кривой коммит, и отменяющий его. git revert HEAD [main 20dea26] Revert "Wrong commit" 1 file changed, 1 deletion(-) PS C:\temp\githowto\repositories\work> git log 20dea26 2025-01-21 | Revert "Wrong commit" (HEAD -> main) [Your Name] c90b848 2025-01-21 | Wrong commit [Your Name] 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] ==== Удаление коммита из истории ==== ''reset'' * Изменит текущую ветку, чтобы она указывала на выбранный коммит. * Опционально сбросит область подготовки до соответствия с указанным коммитом. * Опционально сбросит рабочую директорию до соответствия с указанным коммитом. # Сбросит ветку до коммита v1 (здесь: бесследно удалится 2 последних коммита, откатятся изменения в файлах) git reset --hard v1 # Лог чист git log 204912e 2025-01-21 | Added HTML header (HEAD -> main, tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] # Тем не менее, коммиты ещё есть в списке всех, просто их нет в ветке main git log --all 20dea26 2025-01-21 | Revert "Wrong commit" (tag: wrong) [Your Name] c90b848 2025-01-21 | Wrong commit [Your Name] 204912e 2025-01-21 | Added HTML header (HEAD -> main, tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] На удалённые коммиты можно сослаться либо по хэшу, либо по тэгу, если он есть. Удалённые коммиты, на которые нет ссылок или тэгов, существуют до запуска сборщика мусора. Здесь у одного из удалённых коммитов есть тэг, его надо удалить, чтобы сборщик мусора смог на нём отработать. git tag -d wrong Deleted tag 'wrong' (was 20dea26) # Теперь в списке всех коммитов также нет ошибочных git log --all 204912e 2025-01-21 | Added HTML header (HEAD -> main, tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] Сброс в локальных ветках, как правило, безопасен. Последствия любой ошибки, как правило, можно восстановить простым сбросом с помощью нужного коммита.\\ Однако, если ветка уже стала общедоступной на удаленных репозиториях, сброс может сбить с толку других пользователей ветки. ===== Внесение изменений в коммиты ===== Применяется, когда нужно заменить коммит другим, например, когда что-то просто забыли добавить/удалить/изменить в сделанном коммите. git commit -m "Add copyright" [main 3d91d05] Add copyright 1 file changed, 1 insertion(+) git log 3d91d05 2025-01-22 | Add copyright (HEAD -> main) [Your Name] 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] git add .\hello.html git commit --amend -m "Add copyright with email" [main b0d54f0] Add copyright with email Date: Wed Jan 22 13:41:15 2025 +0300 1 file changed, 1 insertion(+) # Последний коммит заменён на новый git log b0d54f0 2025-01-22 | Add copyright with email (HEAD -> main) [Your Name] 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] Этого же результата можно достичь путем сброса последнего коммита в ветке и повторного коммита новых изменений. ===== Создание веток и переключение между ними ===== # Создать ветку style git switch -c style Switched to a new branch 'style' # Старый способ (не рекомендуется) git checkout -b style git status On branch style nothing to commit, working tree clean # Переключение между ветками (hello.html будет разным после коммитов в ветку style) git switch main cat hello.html git switch style cat hello.html ===== Перемещение файлов ===== Если тупо переименовать или перенести файлы в репозитории, то они будут помечены как удалённые и созданные заново. Связи между этими файлами нет и в истории гита нельзя будет отследить, что откуда взялось. Гит иногда догадывается, что файл был переименован, но рассчитывать на это нельзя. # После обычного переименования/перемещения файлов руками git status On branch style Changes not staged for commit: (use "git add/rm ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) deleted: hello.html deleted: style.css Untracked files: (use "git add ..." to include in what will be committed) css/ index.html no changes added to commit (use "git add" and/or "git commit -a") # Перенести файлы корректно mkdir css git mv style.css css/style.css git mv hello.html index.html git status # Теперь статус в порядке git status On branch style Changes to be committed: (use "git restore --staged ..." to unstage) renamed: style.css -> css/style.css renamed: hello.html -> index.html # Чтобы посмотреть изменения файла до переименования, добавить параметр --follow git log css/style.css 4a6c610 2025-01-22 | Renamed hello.html; moved style.css (HEAD -> style) [Your Name] git log --follow css/style.css 4a6c610 2025-01-22 | Renamed hello.html; moved style.css (HEAD -> style) [Your Name] aa9e5d8 2025-01-22 | Add css [Your Name] ===== Просмотр отличающихся веток ===== # --all - показать все ветки (по умолчанию показывается текущая ветка) # --graph - дерево в виде простых текстовых линий git log --all --graph * b022e6a 2025-01-22 | Add README (HEAD -> main) [Your Name] | * 4a6c610 2025-01-22 | Renamed hello.html; moved style.css (style) [Your Name] | * 632e4e7 2025-01-22 | Include css into hello.html [Your Name] | * aa9e5d8 2025-01-22 | Add css [Your Name] |/ * b0d54f0 2025-01-22 | Add copyright with email [Your Name] * 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] * 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] * 1a3a27e 2025-01-21 | Initial Commit [unknown] ===== Слияние веток ===== Слить ветку main в style # Перейти в ветку style git switch style Switched to branch 'style' # Слить ветки git merge main Merge made by the 'ort' strategy. README | 1 + 1 file changed, 1 insertion(+) create mode 100644 README # График коммитов git log --all --graph * 98277e2 2025-01-22 | Merge branch 'main' into style (HEAD -> style) [Your Name] |\ | * b022e6a 2025-01-22 | Add README (main) [Your Name] * | 4a6c610 2025-01-22 | Renamed hello.html; moved style.css [Your Name] * | 632e4e7 2025-01-22 | Include css into hello.html [Your Name] * | aa9e5d8 2025-01-22 | Add css [Your Name] |/ * b0d54f0 2025-01-22 | Add copyright with email [Your Name] * 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] * 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] * 1a3a27e 2025-01-21 | Initial Commit [unknown] Путем периодического слияния ветки main с веткой style происходит перенос изменений из main и поддерживается совместимость изменений style с изменениями в основной ветке. Однако, это делает графики коммитов уродливыми. Альтернатива слиянию - перебазирование (rebase). ===== Конфликтующие изменения в ветках и разрешение конфликта ===== Если в обеих ветках была изменена одна и та же часть файла, Git может не справиться с автоматическим слиянием изменений. В этом случае Git сообщит о конфликте и попросит разрешить его вручную. Файл index.html ветки style

Hello, World!

Файл hello.html ветки main Hello World Page

Hello, World!

Let's learn Git together.

После попытки слива веток git switch style Switched to branch 'style' git merge main Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. Файл index.html выглядит так: <<<<<<< HEAD:index.html ======= Hello World Page >>>>>>> main:hello.html

Hello, World!

Let's learn Git together.

Часть между ''%%<<<<<<<%%'' и ''%%>>>>>>>%%'' является конфликтом. Верхняя часть соответствует ветке style, которая является текущей веткой (или HEAD) репозитория. Нижняя часть соответствует изменениям из ветки main. Видно, что часть с ''%%

Let's learn Git together.

%%'' git сделал сам. # Можно отменить слияние веток git merge --abort # А можно отредактировать index.html и закоммитить его git add index.html git commit -m "Resolved merge conflict" git status On branch style nothing to commit, working tree clean git log --all --graph * e71d981 2025-01-22 | Resolved merge conflict (HEAD -> style) [Your Name] |\ | * 9e1309b 2025-01-22 | Added meta title (main) [Your Name] * | 98277e2 2025-01-22 | Merge branch 'main' into style [Your Name] |\| | * b022e6a 2025-01-22 | Add README [Your Name] * | 4a6c610 2025-01-22 | Renamed hello.html; moved style.css [Your Name] * | 632e4e7 2025-01-22 | Include css into hello.html [Your Name] * | aa9e5d8 2025-01-22 | Add css [Your Name] |/ * b0d54f0 2025-01-22 | Add copyright with email [Your Name] * 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] * 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] * 1a3a27e 2025-01-21 | Initial Commit [unknown] У Git нет графических инструментов слияния, но [[https://stackoverflow.com/questions/137102/whats-the-best-visual-merge-tool-for-git|можно настроить сторонние]]. ===== rebase вместо merge ===== # В ветке style коммит ''Renamed hello.html; moved style.css'' последний перед слиянием с main. git log --graph * e71d981 2025-01-22 | Resolved merge conflict (HEAD -> style) [Your Name] |\ | * 9e1309b 2025-01-22 | Added meta title (main) [Your Name] * | 98277e2 2025-01-22 | Merge branch 'main' into style [Your Name] |\| | * b022e6a 2025-01-22 | Add README [Your Name] * | 4a6c610 2025-01-22 | Renamed hello.html; moved style.css [Your Name] * | 632e4e7 2025-01-22 | Include css into hello.html [Your Name] * | aa9e5d8 2025-01-22 | Add css [Your Name] |/ * b0d54f0 2025-01-22 | Add copyright with email [Your Name] * 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] * 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] * 1a3a27e 2025-01-21 | Initial Commit [unknown] # Сброс ветки style к этому коммиту git reset --hard HEAD~2 # Вариант: git reset --hard 4a6c610 HEAD is now at 4a6c610 Renamed hello.html; moved style.css # В ветке main есть два коммита, которых нет в ветке style: новый файл README и конфликтующее изменение в файле index.html. # Перенести эти изменения в ветку style с помощью команды rebase. git switch style git rebase main Auto-merging hello.html CONFLICT (content): Merge conflict in hello.html error: could not apply 632e4e7... Include css into hello.html hint: Resolve all conflicts manually, mark them as resolved with hint: "git add/rm ", then run "git rebase --continue". hint: You can instead skip this commit: run "git rebase --skip". hint: To abort and get back to the state before "git rebase", run "git rebase --abort". hint: Disable this message with "git config advice.mergeConflict false" Could not apply 632e4e7... Include css into hello.html git status Опять возник конфликт, но в ''hello.html'', а не в файле ''index.html'', как в прошлый раз. Это связано с тем, что ''rebase'' находился в процессе применения изменений style поверх ветки main. Файл ''hello.html'' в main еще не был переименован, поэтому он все еще имеет старое имя. При слиянии возник бы «обратный» конфликт. При слиянии изменения ветки main были бы применены поверх ветки style. В ветке style файл переименован, поэтому конфликт возник бы в файле ''index.html''. После устранения конфликта можно продолжить rebase (коммит уже не нужен!) git add . git rebase --continue [detached HEAD 31f51f7] Include css into hello.html 1 file changed, 3 insertions(+), 1 deletion(-) Successfully rebased and updated refs/heads/style. git status On branch style nothing to commit, working tree clean git log --graph --all * 53c3dbd 2025-01-22 | Renamed hello.html; moved style.css (HEAD -> style) [Your Name] * 31f51f7 2025-01-22 | Include css into hello.html [Your Name] * d835c42 2025-01-22 | Add css [Your Name] * 9e1309b 2025-01-22 | Added meta title (main) [Your Name] * b022e6a 2025-01-22 | Add README [Your Name] * b0d54f0 2025-01-22 | Add copyright with email [Your Name] * 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] * 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] * 1a3a27e 2025-01-21 | Initial Commit [unknown] Конечный результат перебазирования очень похож на результат слияния. Ветка style в настоящее время содержит все свои изменения, а также все изменения ветки main. Однако, дерево коммитов значительно отличается. Дерево коммитов ветки style было переписано таким образом, что ветка main является частью истории коммитов. Это делает цепь коммитов линейной и гораздо более читабельной. Используйте команду rebase: * Когда вы получаете изменения из удаленного репозитория и хотите применить их к своей локальной ветке. * Если вы хотите, чтобы история коммитов была линейной и легко читаемой. Не используйте команду rebase: * Если текущая ветка является публичной и общей. Переписывание таких веток будет мешать работе других членов команды. * Если важна точная история ветки коммитов (поскольку команда rebase переписывает историю коммитов). Учитывая приведенные выше рекомендации, команду rebase можно использовать для краткосрочных, локальных веток и команду merge для веток в публичном репозитории. ===== Слив в ветку main ===== git switch main git merge style Updating 9e1309b..53c3dbd Fast-forward css/style.css | 3 +++ hello.html => index.html | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 css/style.css rename hello.html => index.html (70%) Т. к. последний коммит в main предшествует последнему коммиту ветки style, Git может выполнить ускоренное слияние, просто переместив указатель ветки вперед, на тот же коммит, что и ветка style. При ускоренном слиянии конфликты не возникают. Кроме того, при ускоренном слиянии не создается фиксация слияния. Теперь ветки style и main идентичны. ===== Несколько репозиториев ===== Клонировать локальный репозиторий cd C:\temp\githowto\repositories git clone work home Cloning into 'home'... done. ls Каталог: C:\temp\githowto\repositories Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 01.02.2025 9:11 home d----- 26.01.2025 11:59 work # Если посмотреть историю, то у обоих репозиториев одинаковые коммиты, но у клонированного добавились ветки # origin/style, origin/main, origin/HEAD git log --all 53c3dbd 2025-01-22 | Renamed hello.html; moved style.css (HEAD -> main, origin/style, origin/main, origin/HEAD) [Your Name] ... ==== origin - указание первичного репозитория ==== При клонировании репозитория исходный сохраняется как origin. Традиционно origin используется в качестве имени первичного централизованного репозитория. git remote origin git remote show origin * remote origin Fetch URL: C:/temp/githowto/repositories/work Push URL: C:/temp/githowto/repositories/work HEAD branch: main Remote branches: main tracked style tracked Local branch configured for 'git pull': main merges with remote main Local ref configured for 'git push': main pushes to main (up to date) ==== Локальные и удалённые ветки ==== Если вывести список веток в клонированном репозитории, то будет видна только main. git branch * main # С параметром -a будут видны все ветки git branch -a * main remotes/origin/HEAD -> origin/main remotes/origin/main remotes/origin/style Ветки в удаленном репозитории не рассматриваются как локальные. Если нужна ветка style, то нужно её создать. ==== Синхронизация изменений из удалённого репозитория ==== ''git fetch'' - получение новых коммитов из удаленного репозитория без изменения локальных веток. # Внесение изменений в удалённый репозиторий cd ../work git add .\README git commit -m "Changed README in original repo" [main 7cc9cfb] Changed README in original repo 1 file changed, 2 insertions(+), 1 deletion(-) # Получение изменений в локальном cd ../home git fetch remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (3/3), 372 bytes | 28.00 KiB/s, done. From C:/temp/githowto/repositories/work 53c3dbd..7cc9cfb main -> origin/main # Коммит приехал, но не интегрировался в локальную ветку main (HEAD не на последнем коммите) # Соответственно, файл локальный файл README не изменился. git log --all 7cc9cfb 2025-02-01 | Changed README in original repo (origin/main, origin/HEAD) [Your Name] 53c3dbd 2025-01-22 | Renamed hello.html; moved style.css (HEAD -> main, origin/style) [Your Name] 31f51f7 2025-01-22 | Include css into hello.html [Your Name] d835c42 2025-01-22 | Add css [Your Name] 9e1309b 2025-01-22 | Added meta title [Your Name] b022e6a 2025-01-22 | Add README [Your Name] b0d54f0 2025-01-22 | Add copyright with email [Your Name] 204912e 2025-01-21 | Added HTML header (tag: v1) [Your Name] 88622c4 2025-01-21 | Added H1 tag (tag: v1-beta) [Your Name] 1a3a27e 2025-01-21 | Initial Commit [unknown] ==== Слияние полученных изменений удалённого репозитория с локальным ==== ''git merge'' сливает полученные ранее изменения в локальный репозиторий. git merge origin/main Updating 53c3dbd..7cc9cfb Fast-forward README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) Теперь файл README изменён и локально. Есть возможность сразу и получить изменения из удалённого репозитория, и сразу слить их в локальный - это ''git pull''.\\ Т. е., ''git pull'' = ''git fetch'' + ''git merge origin/main''. ==== Добавление локальной ветки, отслеживающей удалённую ==== # Добавить ветку style, отслеживающую origin/style git branch --track style origin/style branch 'style' set up to track 'origin/style'. # Локальная ветка style появилась в списке веток git branch -a * main style remotes/origin/HEAD -> origin/main remotes/origin/main remotes/origin/style # и в логе git log --max-count=2 7cc9cfb 2025-02-01 | Changed README in original repo (HEAD -> main, origin/main, origin/HEAD) [Your Name] 53c3dbd 2025-01-22 | Renamed hello.html; moved style.css (origin/style, style) [Your Name] ===== Чистый репозиторий ===== Чистый (голый, bare) репозиторий не имеет рабочего каталога. Он содержит только директорию .git, в которой Git хранит все свои внутренние данные. Обычно используется в качестве удалённого репозитория. Так как bare репозиторий используется только для обмена, то нет причин создавать рабочую копию на диске, проще говоря, такой репозиторий содержит только каталог .git вашего проекта и ничего больше. cd .. # Традиционно "чистый" репозиторий создаётся с .git в конце имени git clone --bare work work.git Cloning into bare repository 'work.git'... done. PS C:\temp\githowto\repositories> ls work.git Каталог: C:\temp\githowto\repositories\work.git Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 02.02.2025 9:39 hooks d----- 02.02.2025 9:39 info d----- 02.02.2025 9:39 objects d----- 02.02.2025 9:39 refs -a---- 02.02.2025 9:39 164 config -a---- 02.02.2025 9:39 73 description -a---- 02.02.2025 9:39 21 HEAD -a---- 02.02.2025 9:39 274 packed-refs ==== Добавление чистого репозитория как удалённого, отправка изменений ==== cd work # Добавить чистый репозиторий work.git как shared git remote add shared ../work.git # Чистые репозитории обычно располагаются на удаленном сервере и туда нельзя зайти, чтобы подтянуть изменения. # Поэтому необходимо как-нибудь передать наши изменения в репозиторий. # Внести изменения, например, в README в репе work и закоммитить git add README git commit -m "Added shared comment to readme" [main 576bd94] Added shared comment to readme 1 file changed, 1 insertion(+), 1 deletion(-) # Передать изменения в чистый репозиторий git push shared main Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 8 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 399 bytes | 66.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To ..\work.git 7cc9cfb..576bd94 main -> main ==== Получение изменений из общего репозитория ==== # Перейти в репозиторий назначения cd ../home # Добавить чистый репозиторий work.git как shared (так же, как ранее в исходном репозитории work) git remote add shared ../work.git # Отслеживать ветку main в shared git branch --track shared main branch 'shared' set up to track 'main'. # Получить изменения из shared/main git pull shared main remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (3/3), 379 bytes | 27.00 KiB/s, done. From ../work * branch main -> FETCH_HEAD * [new branch] main -> shared/main Updating 7cc9cfb..576bd94 Fast-forward README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Теперь файл README изменился и в home. ===== Git-сервер ===== Git умеет быть и сервером. cd .. ls Каталог: C:\temp\githowto\repositories Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 02.02.2025 10:11 home d----- 26.01.2025 11:59 work d----- 02.02.2025 10:06 work.git # Запуск демона git (добавить --enable=receive-pack, чтобы разрешить push. Внимание: # сервер не производит аутентификацию, поэтому любой сможет отправлять изменения в ваш репозиторий!) git daemon --verbose --export-all --base-path=. [20528] Ready to rumble # Это появляется позже после подключения клиента [21436] Connection from [::1]:34050 [21436] unable to set SO_KEEPALIVE on socket: Input/output error [21436] Extended attribute "host": localhost [21436] Extended attribute "protocol": version=2 [21436] Request upload-pack for '/work.git' В другом окне терминала (прошлое занято выполняющимся сервисом): cd C:\temp\githowto\repositories # Клонировать work.git с сервера в локальный net_work git clone git://localhost/work.git net_work Cloning into 'net_work'... remote: Enumerating objects: 33, done. remote: Counting objects: 100% (33/33), done. remote: Compressing objects: 100% (25/25), done. remote: Total 33 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0) Receiving objects: 100% (33/33), done. Resolving deltas: 100% (4/4), done. # Файлы появились ls net_work Каталог: C:\temp\githowto\repositories\net_work Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 02.02.2025 10:22 css -a---- 02.02.2025 10:22 295 index.html -a---- 02.02.2025 10:22 100 README