.NET Разработчик
6.53K subscribers
442 photos
3 videos
14 files
2.12K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1527. #TipsAndTricks #Git
Некоторые Малоизвестные Приемы в
Git
Сегодня несколько полезных советов при работе с Git для любителей консоли.

1. Изменение последнего коммита
Когда вы делаете коммит в репозитории Git, вы создаёте новый снимок своего кода. Иногда вы можете обнаружить, что забыли включить файл, допустили опечатку в сообщении коммита или внесли другие небольшие изменения, которые хотели бы включить в последний коммит. Git позволяет изменить последний коммит с помощью флага --amend:
# изменить последний коммит новым сообщением
git commit --amend -m "New message"

# изменить, не меняя сообщения
git commit --amend --no-edit

2. Reflog
Git отслеживает все изменения, которые вы вносите в репозиторий, включая коммиты, слияния и другие операции. Reflog — это журнал всех изменений в репозитории Git, включая все коммиты, изменения веток и другие операции. Вы можете использовать журнал ссылок для восстановления потерянных коммитов, возврата к предыдущему состоянию или отмены перебазирования.
Чтобы просмотреть журнал ссылок, запустите:
git reflog

# возврат к предыдущему состоянию
git reset HEAD@{N}

3. Интерактивное перебазирование
Это мощный инструмент, который позволяет редактировать, изменять порядок или удалять коммиты перед их слиянием с основной веткой. Это особенно полезно, когда вы работаете над функциональной веткой и хотите очистить историю коммитов перед её слиянием с основной веткой:
git rebase -i HEAD~N

# изменить сообщение коммита
pick 1234567 Old message
reword 2345678 New message

# изменить порядок коммитов
pick 1234567 First commit
pick 2345678 Second commit
pick 3456789 Third commit

# удалить коммит
pick 1234567 First commit
drop 2345678 Second commit
pick 3456789 Third commit

4. Git-псевдонимы
Псевдонимы Git позволяют создавать собственные ярлыки для команд Git. Это может сэкономить ваше время и объём ввода, особенно для часто используемых команд:
git config --global alias.ci commit

# использование
git ci -m "Commit message"

5. Git Stash
Git stash позволяет временно сохранять изменения, которые вы ещё не готовы зафиксировать, без создания новой ветки:
git stash

# применить последние сохранённые изменения
git stash apply

# применить выбранные сохранённые изменения
git stash apply stash@{N}

# список всех изменений
git stash list

Больше консольных команд Git в этом посте.

Источник: https://dev.to/atordvairn/some-secret-git-tricks-that-come-in-handy-2k8i
👍17
День 1737. #ЗаметкиНаПолях #Git
Организация Нескольких Идентичностей в
Git
Короткий совет, как управлять несколькими идентичностями в Git. Например, личными проектами, рабочими, и раздельно для каждого клиента.

Я организую свои репозитории Git в три уровня. Мои личные проекты находятся в каталоге ~/sources. Все рабочие проекты находятся в ~/work. Это первый уровень.
Уровень 2 — это клиент, например, ~/work/client1.
Уровень 3 — это репозиторий проекта, например, ~/work/client1/foo-api.

Вот как организован рабочий каталог:
/Users/garrit/work
├── client1
│ ├── foo-api
│ ├── foo-ios
│ └── foo-android
└── client2
├── bar-ios
└── bar-middleware


Теперь предположим, что client2 требует, чтобы мы делали коммиты с идентичностью, отличной от нашей рабочей электронной почты по умолчанию. Кроме того, у вас, вероятно, также есть личный адрес электронной почты для ваших проектов.

.gitconfig – это глобальный файл конфигурации Git, расположенный в корневом каталоге. Если вы когда-либо задавали такой параметр, как git config user.name «Foo Bar»: именно здесь он и сохранялся.

Одна из замечательных особенностей файла .gitconfig заключается в том, что вы можете условно включать в него другие файлы конфигурации, и в этом вся суть:
[user]
name = Garrit Franke
email = garrit@slashdev.space

[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work

[includeIf "gitdir:~/work/client2/"]
path = ~/.gitconfig-client2

[includeIf "gitdir:~/sources/"]
path = ~/.gitconfig-personal

# ...

По умолчанию мое имя и адрес электронной почты всегда соответствуют моей личной информации. Я также храню здесь некоторые другие глобальные настройки, но они нам сейчас не важны. Если репозиторий расположен внутри каталога ~/work, в него включается файл с именем ~/.gitconfig-work. Это просто ещё один файл gitconfig. Вот как он выглядит в моём случае:
[user]
name = Garrit Franke
signingkey = 12345678
email = garrit@work.de

[commit]
gpgsign = true


Надеюсь, идея понятна. Для каждой идентичности вы сохраняете отдельный файл gitconfig и включаете его в основной файл ~/.gitconfig. Важно отметить, что для этого вам необходимо организовать ваши репозитории, сгруппировав их по клиентам.

Этот трюк немного упростил адаптацию моего проекта. Больше никаких запросов от клиентов «Вы забыли обновить свой email»!

Источник: https://garrit.xyz/posts/2023-10-13-organizing-multiple-git-identities
Автор оригинала: Garrit Franke
👍27
День 1868. #Шпаргалка #Git
Популярные Настройки
Git Config. Начало
Джулия Эванс спросила у коллег-программистов мнения о самых популярных и полезных настройках Git, которые они используют. Вот такой список получился.

Описание всех настроек можно найти в документации Git.

1. pull.ff only или pull.rebase true
Эти две были самыми популярными. Обе они преследуют схожие цели: избежать случайного создания коммита слияния при запуске git pull на ветке, где восходящая ветвь расходится.
- pull.rebase true эквивалентен запуску git pull --rebase каждый раз,
- pull.ff only эквивалентен запуску git pull --ff-only каждый раз.
Скорее всего, нет смысла устанавливать обе одновременно, поскольку --ff-only переопределяет --rebase.

2. merge.conflictstyle zdiff3
Делаем конфликты слияний более читабельными!
По умолчанию в git конфликты слияния выглядят так:
<<<<<<< HEAD
def parse(input):
return input.split("\n")
=======
def parse(text):
return text.split("\n\n")
>>>>>>> somebranch

Вам предлагается решить, что лучше: input.split("\n") или text.split("\n\n"). Но как? Что делать, если вы не помните, нужно \n или \n\n?
Вот как выглядит тот же конфликт слияния с merge.conflictstyle diff3:
<<<<<<< HEAD
def parse(input):
return input.split("\n")
||||||| base
def parse(input):
return input.split("\n\n")
=======
def parse(text):
return text.split("\n\n")
>>>>>>> somebranch

Здесь содержится дополнительная информация: теперь исходная версия кода находится посередине! Итак, мы видим:
- одна сторона изменила \n\n на \n,
- другая сторона переименовала input в text.
Поэтому, по-видимому, правильным решением конфликта слияния является return text.split("\n"), поскольку он объединяет изменения с обеих сторон.
zdiff3 — это тот же diff3, но он лучше выносит любые общие строки в начале или конце за пределы зоны конфликта. То есть, если обе стороны сделали изменения, которые имеют общие строки в начале или в конце, то они будут корректно слиты и не будут входить в зону конфликта.

3. rebase.autosquash true
Цель autosquash — упростить модификацию старых коммитов. Допустим, у вас есть коммит с исправлением другого коммита (3 коммита назад), который вы хотели бы объединить с ним. Вы фиксируете новый коммит с помощью git commit --fixup OLD_COMMIT_ID, что даёт новому коммиту сообщение «fixup! …».
Теперь, когда вы запускаете git rebase --autosquash main, он автоматически объединяет все коммиты-исправления (fixup!) со своими целями.
rebase.autosquash true означает, что --autosquash всегда автоматически передаётся в git rebase.

4. rebase.autostash true
Это автоматически запускает git stash перед git rebase и git stash pop после. По сути, он передаёт --autostash в git rebase. Это означает, что вы можете запустить rebase на «грязном» рабочем дереве. Однако будьте осторожны: применение изменений из stash после успешного перебазирования может привести к нетривиальным конфликтам. Хотя, похоже, это не очень часто встречается у людей, поскольку этот вариант конфигурации кажется действительно популярным.

Продолжение следует…

Источник:
https://jvns.ca/blog/2024/02/16/popular-git-config-options/
👍13
День 1869. #Шпаргалка #Git
Популярные Настройки
Git Config. Продолжение
Начало

5. push.default simple и push.default current
Параметры push.default сообщают git push автоматически отправлять текущую ветку в удалённую ветку с тем же именем.
- push.default simple — значение по умолчанию в Git. Это работает только в том случае, если ваша ветка уже отслеживает удалённую ветку.
- push.default current - аналогична, но она всегда передаёт локальную ветку в удалённую ветку с тем же именем.
current кажется хорошей настройкой, если вы уверены, что никогда случайно не создадите локальную ветку с тем же именем, что и несвязанная удалённая ветка. У многих людей есть соглашения об именах веток (например, julia/my-change), которые делают конфликты такого рода маловероятными, либо у них просто мало сотрудников, поэтому конфликтов имён ветвей, вероятно, не происходит.

6. init.defaultBranch main
Создавать ветку main вместо ветки master при создании нового репозитория.

7. commit.verbose true
Добавит все различия коммита в текстовый редактор, где вы пишете сообщение о коммите, чтобы помочь вам запомнить, что вы делали.

8. rerere.enabled true
Позволяет использовать функцию rerere (reuse recovered resolution - повторно использовать восстановленное разрешение), которая запоминает, как вы разрешали конфликты слияния во время git rebase, и автоматически разрешает конфликты за вас, когда это возможно.

9. help.autocorrect 10
Если git обнаружит опечатки и сможет определить ровно одну действительную команду, аналогичную ошибке, он попытается предложить правильную команду или даже автоматически запустить предложение. Возможные значения:
- 0 (по умолчанию) - показать предложенную команду.
- положительное число - запустить предложенную команду через указанные децисекунды (0,1 секунды).
- "immediate" - немедленно запустить предложенную команду.
- "prompt" - показать предложение и запросить подтверждение для запуска команды.
- "never" - не запускать и не показывать предлагаемые команды.

10. core.pager delta
«Пейджер» — это то, что git использует для отображения результатов git diff, git log, git show и т. д.
delta – это модный инструмент для просмотра различий с подсветкой синтаксиса.

11. diff.algorithm histogram
Алгоритм сравнения Git по умолчанию часто плохо справляется с переупорядочением функций. Например:
-.header {
+.footer {
margin: 0;
}

-.footer {
+.header {
margin: 0;
+ color: green;
}

Это сильно путает. Но с diff.algorithm histogram всё становится гораздо понятнее:
-.header {
- margin: 0;
-}
-
.footer {
margin: 0;
}

+.header {
+ margin: 0;
+ color: green;
+}

Ещё один популярный вариант - patience.

12. core.excludesFile – глобальный .gitignore
core.excludesFile = ~/.gitignore позволяет установить глобальный файл gitignore, который применяется ко всем репозиториям, для таких вещей, как .idea или .vs, которые вы никогда не хотите коммитить в какой-либо репозиторий. По умолчанию это ~/.config/git/ignore.

Окончание следует…

Источник:
https://jvns.ca/blog/2024/02/16/popular-git-config-options/
👍12
День 1870. #Шпаргалка #Git
Популярные Настройки
Git Config. Окончание
Начало
Продолжение

13. includeIf: отдельные конфигурации git для личного и рабочего
Многие используют это для настройки разных email для личных и рабочих репозиториев. Вы можете настроить это примерно так:
[includeIf "gitdir:~/code/<work>/"]
path = "~/code/<work>/.gitconfig"


14. url."git@github.com:".insteadOf 'https://github.com/'
Если вы часто случайно клонируете HTTP-версию репозитория вместо SSH-версии, а затем приходится вручную заходить в ~/.git/config и редактировать удалённый URL, это заменит https://github.com в удалённых репозиториях на git@github.com:
[url "git@github.com:"]
insteadOf = https://github.com/

Кто-то вместо этого использует pushInsteadOf для замены только в git push, потому что не хочет разблокировать свой SSH-ключ при извлечении из общедоступного репозитория.

15. fsckobjects
Проверяет получаемые/отправляемые объекты. Если будет обнаружено повреждение или ссылка на несуществующий объект, операция прервётся:
transfer.fsckobjects = true
fetch.fsckobjects = true
receive.fsckObjects = true

16. Остальное
- blame.ignoreRevsFile .git-blame-ignore-revs
Позволяет указать файл с коммитами, который следует игнорировать во время git blame, чтобы гигантские переименования не мешал.
- branch.sort -committerdate
Заставит git branch сортировать ветки по последнему использованию, а не по алфавиту, чтобы упростить поиск ветвей. tag.sort taggerdate аналогично для тегов.
- color.ui false
Отключает подстветку.
- core.autocrlf false
В Windows для работы совместно с коллегами на Unix.
- core.editor emacs
Использовать emacs (или другой редактор) для сообщений коммита.
- diff.tool difftastic
Использовать difftastic (или другой редактор) для отображения различий.
- merge.tool meld
Использовать meld (или другой редактор) для разрешения конфликтов слияния.
- fetch.prune true и fetch.prunetags
Автоматически удалит локальные ветки и теги, которых больше нет в удалённом репозитории.
- gpg.format ssh
Позволит подписывать коммиты ключами SSH.
- log.date iso
Отобразит даты как 2024-03-14 15:54:51 вместо Thu Mar 14 15:54:51 2024
- merge.keepbackup false
Чтобы избавиться от файлов .orig, которые git создаёт при слиянии конфликтов.
- push.followtags true
Добавит новые теги вместе с добавляемыми коммитами.
- rebase.missingCommitsCheck error
Не позволит удалять коммиты во время rebase.

Источник: https://jvns.ca/blog/2024/02/16/popular-git-config-options/
👍7
День 2098. #Git #TipsAndTricks
Советы по
Git: Предыдущие Ветки
Сегодня рассмотрим два совета, как легко переключаться между ветками вперед-назад и как получить последние использованные ветки.

Переключение между ветками
Представьте, что вы находитесь на ветке feature-1 и хотите переключиться на ветку main, чтобы выполнить там какую-то работу. После того, как вы закончите работу на main, вы хотите переключиться обратно на feature-1.

Не зная точного имени ветки, вы можете использовать:
git checkout -

или (начиная с версии Git 2.23):
git switch -


На самом деле, это сокращённая версия следующей команды:
git checkout @{-1}

Эта команда позволяет вернуться к любой предыдущей ветке.

Получение последних 5 использованных веток
Если вы хотите увидеть последние 5 веток, которые вы использовали, вы можете выполнить следующую команду:
git reflog | grep -o 'checkout: moving from [^ ]* to [^ ]*' | awk '{print $NF}' | awk '!seen[$0]++' | head -n 5 

Это работает с git bash и такими ОС, как Linux и MacOS. Идея заключается в использовании reflog для получения истории веток, которые вы извлекали. Команда grep фильтрует вывод, чтобы показывать только ветки, которые вы извлекли. Первая команда awk извлекает имена веток из вывода. Вторая команда awk удаляет дубликаты. Команда head ограничивает вывод последними 5 ветками. Поэтому, если вам нужны только последние 3 ветки, которые вы извлекли, вы можете изменить head -n 5 на head -n 3.

Источник: https://steven-giesel.com/blogPost/bbfb8333-e05a-4de7-88b9-17ac2248d77f/git-tricks-get-the-last-checked-out-branch
👍19
День 2332. #ЗаметкиНаПолях #Git
Объединяем Репозитории
Git, Сохраняя Историю
Объединение двух репозиториев Git может быть полезным в сценариях, когда вы хотите объединить связанные проекты в один репозиторий для более простого управления, совместной работы и контроля версий.

Этот подход особенно полезен, когда два репозитория имеют общую цель или тесно связаны, поскольку он упрощает управление зависимостями и гарантирует, что весь связанный код находится в одном месте. Кроме того, он может оптимизировать рабочие процессы, уменьшая необходимость переключения между репозиториями и упрощая отслеживание изменений в объединённой кодовой базе.

Используя Git, вы можете объединить два репозитория, сохранив их истории коммитов. Этот процесс гарантирует, что история обоих репозиториев останется нетронутой, что позволит вам отслеживать изменения и понимать эволюцию кодовой базы. Сохраняя историю коммитов, вы сохраняете ценный контекст о прошлых модификациях, авторстве и причинах конкретных изменений.
# Клонируем первый репозиторий
git clone https://github.com/mygit/project1.git project1
cd project1

# Добавляем второй репозиторий как удалённый (remote) и скачиваем
git remote add project2 https://github.com/mygit/project2.git
git fetch project2

# Сливаем второй репозиторий в первый
git merge project2/main --allow-unrelated-histories

# TODO: Разрешаем любые возникшие конфликты слияния и фиксируем изменения

# Делаем push объединённого репозитория в новую удалённую ветку
git push origin main


Источник: https://www.meziantou.net/merging-2-git-repositories-into-one.htm
👍15