Библиотека Go-разработчика | Golang
24K subscribers
2.6K photos
48 videos
88 files
5.13K links
Все самое полезное для Go-разработчика в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/32d20779

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0

#WXSSA
Download Telegram
🔒 CORS-мидлвар для Go, который сложно настроить неправильно

CORS это тема, где легко допустить ошибку в конфигурации и не заметить этого. Разрешить все origins через *, забыть проверить preflight, или написать паттерн, который пропускает лишнее. Библиотека jub0bs/cors построена так, чтобы минимизировать такие сценарии.

Что это такое

jub0bs/cors — мидлвара для стандартного net/http, которая реализует CORS-протокол строго по спецификации Fetch standard. Автор позиционирует её как более безопасную альтернативу популярной rs/cors: API спроектирован так, что небезопасные конфигурации просто не дают себя создать.

Как это работает

Создаём мидлвару через cors.NewMiddleware, передаём конфиг, оборачиваем нужный ServeMux:
package main

import (
"io"
"log"
"net/http"

"github.com/jub0bs/cors"
)

func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", handleHello) // CORS здесь не настроен

corsMw, err := cors.NewMiddleware(cors.Config{
Origins: []string{"https://example.com"},
Methods: []string{http.MethodGet, http.MethodPost},
RequestHeaders: []string{"Authorization"},
})
if err != nil {
log.Fatal(err) // плохая конфигурация — ошибка сразу, не в рантайме
}
corsMw.SetDebug(true) // включить debug-режим при разработке

api := http.NewServeMux()
api.HandleFunc("GET /users", handleUsersGet)
api.HandleFunc("POST /users", handleUsersPost)
mux.Handle("/api/", http.StripPrefix("/api", corsMw.Wrap(api)))

if err := http.ListenAndServe(":8080", mux); err != http.ErrServerClosed {
log.Fatal(err)
}
}


Маршрут /hello не попадает под CORS — мы явно применяем мидлвару только к /api/. Это позволяет настраивать CORS точечно, а не на всё приложение сразу.

Что выделяет библиотеку

Валидация конфига происходит при старте. Если что-то не так — NewMiddleware возвращает ошибку сразу, не в момент обработки запроса. Никаких сюрпризов в продакшне.

Есть debug-режим: при включённом SetDebug(true) мидлвара добавляет в ответ заголовки с объяснением, почему preflight провалился. Это удобно при разработке и легко отключается в продакшне.

Мидлвару можно перенастраивать на лету через метод Reconfigure без перезапуска сервера. Это потокобезопасно.

Ошибки конфигурации можно обрабатывать программно через пакет cfgerrors — например, для формирования ответа в формате RFC 9457 (Problem Details).

По бенчмаркам автора библиотека быстрее rs/cors, хотя для большинства проектов это не принципиально.

Чего библиотека не умеет

Она намеренно ограничена. Нельзя задать произвольный паттерн для origins — только конкретные значения из заранее определённого набора форматов. Нельзя логировать каждый запрос через мидлвару. Нельзя менять статус-код preflight-ответа (всегда 204). Автор объясняет эти ограничения соображениями безопасности и соответствия спецификации.

Строгий по умолчанию, с валидацией на старте, debug-режимом и возможностью перенастройки без рестарта.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72🔥2
Почему в Go невозможно поставить открывающую фигурную скобку на новой строке

Многие думают, что это просто линтер или code style. Но причина куда глубже и она спрятана в самом сердце компилятора, на уровне, до которого добираются немногие.

// Так написать не получится — будет ошибка компиляции
func foo()
{
fmt.Println("hello")
}


Подсказка: подумайте, что происходит до того, как парсер вообще увидит ваш код 👀

Ответ: вы сами знаете где

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱63👍2
🛠 CLI для PostgreSQL с автодополнением

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

pgxcli это интерактивный CLI для PostgreSQL, написанный на Go. Он добавляет подсветку SQL прямо в терминале, автодополняет ключевые слова и команды, сохраняет историю сессий и поддерживает стандартные команды PostgreSQL: \d, \l, \dt, \q.

Как подключиться

Несколько вариантов на выбор:
# Позиционные аргументы
pgxcli mydb myuser

# Флаги
pgxcli --host localhost --port 5432 --user postgres --dbname postgres

# URI
pgxcli postgres://user:password@localhost:5432/dbname

# Интерактивная форма подключения
pgxcli -i


Установка:
go install github.com/balaji01-4d/pgxcli/cmd/pgxcli@latest


Конфигурация

При первом запуске создаётся конфиг по пути ~/.config/pgxcli/config.toml. Там можно настроить стиль промпта и цветовую схему.

Стоит ли использовать вместо pgcli

pgxcli пока молодой проект, версия v0.1.0 вышла в конце апреля 2026 года. Преимущество одно — это единый бинарник без внешних зависимостей с быстрым стартом.

В планах стриминг результатов для больших таблиц, экспорт в CSV, Excel и SQL, просмотр таблиц через браузер.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
10
🖇 Новый пакет для поддержки JIT-компиляторов и встроенных VM

В трекере Go появился proposal #78189. Он предлагает добавить стандартный пакет runtime/jit, который позволит Go-рантайму корректно работать с динамически генерируемым кодом.

В чём проблема

Go компилирует код заранее. Стек-анвайндер рантайма устроен так, что знает только о функциях, зарегистрированных в moduledata на этапе линковки.

Если на стеке оказывается счётчик команд из динамически сгенерированного кода — JIT-компилятора, WASM-рантайма или встроенной VM — рантайм падает с фатальной ошибкой:
runtime: unexpected return pc for somefunc called from 0x7f4a12340010
fatal error: unknown caller pc


Это затрагивает любую программу, которая встраивает JIT, например, база данных компилирует SQL в нативный код, хостит WASM, использует FFI с трамплинами или встраивает скриптовые VM вроде Lua.

Единственный обходной путь сегодня — не вызывать Go-функции из динамического кода вообще, либо использовать промежуточные C-фреймы через cgo, что добавляет около 40 наносекунд накладных расходов и требует cgo-тулчейна.

Что предлагают

Новый пакет runtime/jit с минимальным API. Ключевые части:

Region — структура, описывающая регион исполняемой памяти. Содержит колбэки для анвайндинга (Next), описания фреймов в трейсбеке (Describe) и сканирования корней GC (ScanStack).

Три режима анвайндинга:

UnwindStop
— трейсбек обрывается на JIT-фрейме
UnwindSkip — рантайм пропускает пользовательские фреймы и продолжает
UnwindDeclare — пропускает и описывает фреймы в трейсбеке.

handle := jit.Register(jit.Region{
Lo: uintptr(codeStart),
Hi: uintptr(codeEnd),
Unwind: jit.UnwindDeclare,
Next: myUnwindNext,
Describe: myDescribe,
ScanStack: myScanStack,
})
defer handle.Unregister()


Для кооперации со шедулером — функция Preempt(). JIT-код вызывает её в точках безопасности (заголовки циклов, входы в функции) и возвращает управление Go, если шедулер или GC запросили остановку.

Как это работает внутри

Реестр регионов построен на copy-on-write с атомарным свапом указателя. Анвайндер получает доступ к нему без блокировок. Патчи в traceback.go проверяют пользовательские регионы перед тем, как бросить ошибку на неизвестный счётчик команд. GC получает хук в markroot() для вызова ScanStack.

Горутина остаётся в состоянии _Grunning пока выполняется JIT-код — никакого переключения состояний, никакого освобождения. Это принципиальное отличие от cgocall, который обращается с чужим кодом как с чёрным ящиком.

Статус

Proposal открыт в марте 2026 года. Реализация около 500 строк кода, 15 тестов, трамплины для всех 13 Linux-архитектур. Проверена в продакшне в движке базы данных MemCP.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍164👾1
🤖 ИИ-интервью, архетипы египетских богов и симуляция роли гендиректора

Сбер тестирует кандидатов по архетипам Маат, Исиды и Бастет. Яндекс ввёл обязательный fit-интервью и единую систему оценки. А ГигаРекрутер в Telegram уже проводит первичные интервью вместо живого HR.

Что реально происходит на рынке IT-найма и как к этому готовиться ➡️ читайте в статье

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
3👾3😁2
⚡️ Быстрый JSON от ByteDance

Стандартная библиотека encoding/json в Go работает медленно на больших объёмах данных. Если сервис обрабатывает тысячи запросов в секунду с тяжёлыми JSON-структурами, это становится заметным узким местом.

Sonic это библиотека для сериализации и десериализации JSON, которая использует JIT-компиляцию и SIMD-инструкции процессора. Она полностью совместима с API encoding/json, то есть замена происходит в одну строку.

Что под капотом

Sonic генерирует машинный код под конкретную схему данных прямо во время выполнения, а не в момент компиляции. SIMD позволяет обрабатывать несколько байт одновременно на уровне железа.

В итоге на средних JSON (13 КБ, 300+ ключей) скорость кодирования достигает 2468 МБ/с против 792 МБ/с у стандартной библиотеки.

Установка:
go get github.com/bytedance/sonic


Базовое использование

Замена encoding/json буквально в одну строку:
import "github.com/bytedance/sonic"

var data YourSchema

// Кодирование
output, err := sonic.Marshal(&data)

// Декодирование
err := sonic.Unmarshal(output, &data)


Стриминг

Sonic поддерживает потоковое чтение из io.Reader и запись в io.Writer:

var o = map[string]interface{}{}
var r = strings.NewReader(`{"a":"b"}{"1":"2"}`)
var dec = sonic.ConfigDefault.NewDecoder(r)
dec.Decode(&o)
dec.Decode(&o)
fmt.Printf("%+v", o)
// map[1:2 a:b]


Частичный парсинг через ast.Node

Если нужно вытащить одно поле из большого JSON, не парся всё целиком:
import "github.com/bytedance/sonic"

node, err := sonic.GetFromString(twitterJson, "statuses", 3, "user")
var user User
err = sonic.UnmarshalString(node.Raw(), &user)


Pretouch для тяжёлых схем

Sonic компилирует код при первом вызове. Если схема большая, первый запрос может подвиснуть.

Чтобы этого избежать, компилируем заранее при старте приложения:
import (
"reflect"
"github.com/bytedance/sonic"
)

func init() {
var v HugeStruct
err := sonic.Pretouch(reflect.TypeOf(v))
}


Готовые конфиги

sonic.ConfigDefault — быстрый режим по умолчанию

sonic.ConfigStd — совместимый со стандартной библиотекой

sonic.ConfigFastest — максимальная скорость, без дополнительных проверок

На платформах без поддержки JIT Sonic автоматически откатывается к encoding/json.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍9🔥3
🦾 Почему ваши AI-продукты на базе LLM ломаются (и как это чинить)?

Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало».

🗓️ Когда: 14 мая в 19:00 МСК
⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы

🧑🏻‍💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы.

🎁 Главный бонус для онлайна:
Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps.

👉 Занять место на вебинаре
🥱4👍1
🔄 oapi-codegen v2.7.0

Вышел релиз oapi-codegen v2.7.0. Это Go-инструмент, который генерирует серверный и клиентский код из OpenAPI-спецификаций. Версия исправляет проблемы с allOf/anyOf/oneOf, внешними $ref, перечислениями и обходом схем.

Три изменения, которые затронут существующий код

1. Strict-server с внешними $ref на ответы

Если strict-server использует внешний $ref на components/responses/... из другой спецификации, эта спецификация теперь тоже должна генерироваться с strict-server: true.

Добавьте в конфиг источника:
generate:
models: true
strict-server: true


2. Переименование анонимных схем

Анонимные схемы внутри oneOf, anyOf и additionalProperties теперь генерируются по единому шаблону:
GetPets_200_Data_Item            →  GetPets200JSONResponseBody_Data_Item
GetPets200JSONResponse_Data_Item → GetPets200JSONResponseBody_Data_Item


3. Инлайн middleware-типы в strict-server

StrictHandlerFunc и StrictMiddlewareFunc больше не являются алиасами к типам из пакета runtime/strictmiddleware/<framework>.

Теперь они определяются прямо в сгенерированном коде:
// было
import strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc

// стало
type StrictHandlerFunc func(ctx echo.Context, request any) (any, error)


Если вы ссылались на типы вида strictecho.StrictEchoHandlerFunc напрямую, замените их на StrictHandlerFunc из сгенерированного пакета.

Что нового

Разрешение коллизий имён. Новая опция output-options.resolve-type-name-collisions: true позволяет генерировать код, когда два разных определения претендуют на одинаковое Go-имя.

Коллизия разрешается детерминированно через суффикс:
type Status string          // из components.schemas.Status
type StatusParameter = string // из components.parameters.Status


Опция отключена по умолчанию.

Полная матрица параметров. Теперь поддерживаются все комбинации style × explode × type для параметров пути, запроса, заголовков и куки. Если раньше падала ошибка unsupported style или поведение отличалось в разных бэкендах, регенерация должна это исправить. Требуется github.com/oapi-codegen/runtime версии v1.4.0 или выше.

Опциональные заголовки ответов. В strict-server необязательные заголовки теперь генерируются как указатели. Если поле nil, заголовок не отправляется:
// было
type GetFoo200ResponseHeaders struct {
XOptional string // всегда в ответе, даже пустым
}

// стало
type GetFoo200ResponseHeaders struct {
XOptional *string // nil — заголовок не отправляется
}


Старое поведение возвращается через compatibility.headers-implicitly-required: true.

Echo v5. Добавлена поддержка Echo v5 через флаг generate.echo5-server: true. Echo v4 не затронут.

Middleware на уровне операций в Echo. В RegisterHandlersWithOptions появился OperationMiddlewares:
api.RegisterHandlersWithOptions(e, server, api.RegisterHandlersOptions{
OperationMiddlewares: map[string][]echo.MiddlewareFunc{
"createPet": {authMiddleware, auditMiddleware},
},
})


Middleware на уровне хендлеров в Fiber. В FiberServerOptions появился слайс HandlerMiddlewares []HandlerMiddlewareFunc.

Обработчики ошибок в strict-server для Gin. Теперь Gin поддерживает RequestErrorHandlerFunc и ResponseErrorHandlerFunc в StrictServerOptions, как это уже было в Echo.

Требования к окружению

Для сборки и запуска oapi-codegen теперь нужен Go 1.24.4+. Сгенерированный код по-прежнему может работать на более старых версиях. Из-за транзитивных зависимостей может потребоваться зафиксировать версии:
github.com/speakeasy-api/jsonpath v0.6.3
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936


➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42🤩2🔥1👾1
👨‍💻 Менеджер SSH-туннелей, который не мешает работать

Вы настроили SSH-туннель, отошли на час, вернулись, а соединение упало. Поднимаете снова вручную. Через день история повторяется. Если туннелей несколько, это превращается в рутину.

boring решает именно это. Он держит туннели живыми, переподключает их автоматически и управляет всем через один TOML-файл.

Что умеет

Поддерживает три режима проброса портов: локальный, удалённый и динамический через SOCKS5. Работает с ~/.ssh/config и ssh-agent, если хост уже описан там, достаточно указать его имя. Умеет работать с Unix-сокетами. Есть автодополнение для bash, zsh и fish.

Бинарник появится в папке dist. Его нужно переложить в любую директорию из $PATH.

Пример конфига с двумя туннелями:
# туннель к dev-серверу, хост берётся из SSH config
[[tunnels]]
name = "dev"
local = "9000"
remote = "localhost:9000"
host = "dev-server"

# туннель к prod с явными параметрами
[[tunnels]]
name = "prod"
local = "5001"
remote = "localhost:5001"
host = "prod.example.com"
user = "root"
identity = "~/.ssh/id_prod"


Каждый туннель описывается несколькими полями. Обязательные: name, local, remote, host. Остальное опционально, boring подтянет нужное из SSH config или использует значения по умолчанию.

Основные команды:
boring list          # показать все туннели
boring open dev # открыть туннель по имени
boring open -a # открыть все туннели сразу
boring close dev # закрыть туннель
boring edit # открыть файл конфигурации


Поддерживаются glob-паттерны. Можно открыть сразу несколько туннелей командой вида boring open prod*.

Keep-alive

По умолчанию boring отправляет keep-alive каждые 120 секунд. Значение можно переопределить глобально или на уровне конкретного туннеля:
keep_alive = 60  # в секундах

[[tunnels]]
name = "flaky-server"
keep_alive = 30
...


boring не требует демона, не тянет зависимостей и не лезет в системные настройки. Один бинарник, один TOML-файл и туннели просто работают в фоне.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83👾1
🍵 Почтовый клиент прямо в терминале

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

matcha это TUI-клиент для работы с email, написанный на Go с использованием библиотеки Bubble Tea. Работает прямо в консоли, поддерживает несколько аккаунтов, вложения, черновики и даже отображение изображений в письмах, если терминал это позволяет.

Что умеет

Читать и отправлять письма, отвечать с цитированием, скачивать вложения, искать по входящим. Поддерживает Gmail, iCloud и любой кастомный IMAP/SMTP.

Если пишете письмо в Markdown клиент сам конвертирует его в HTML перед отправкой. Черновики сохраняются автоматически при выходе из редактора.

Навигация в стиле Vim: j/k для движения по списку, r для обновления входящих, / для поиска, d для удаления.

Настройка

При первом запуске клиент попросит указать email, пароль и провайдера. Конфиг хранится в ~/.config/matcha/config.json. Для Gmail и iCloud нужен app-specific password, обычный пароль от аккаунта не подойдёт.

Важно знать: пароли хранятся в конфиге в открытом виде. Авторы сами об этом предупреждают.

Если терминал это ваша основная рабочая среда, matcha позволяет не выходить из неё ради почты.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2
🌐 HTTP-клиент для Go с имитацией браузера

surf — продвинутый HTTP-клиент для Go. Он поддерживает имитацию браузерных отпечатков, HTTP/2 и HTTP/3, сессии, middleware, стриминг и многое другое.

Зачем это нужно

Стандартный net/http выдаёт себя по TLS-отпечатку. Большинство защищённых сайтов различают настоящий браузер и скрипт именно по нему. surf эмулирует не только заголовки, но и низкоуровневые параметры TLS-рукопожатия, порядок заголовков и настройки QUIC.

Как это работает

Простой GET-запрос выглядит так:
resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
if resp.IsErr() {
log.Fatal(resp.Err())
}
fmt.Println(resp.Ok().Body.String().Unwrap())


Имитация Chrome с сессией:
client := surf.NewClient().
Builder().
Impersonate().Chrome().
Session().
Build().
Unwrap()

resp := client.Get("https://example.com").Do()


Firefox со случайной ОС:
client := surf.NewClient().
Builder().
Impersonate().
RandomOS().
Firefox().
Build().
Unwrap()


HTTP/3 с полным QUIC-отпечатком:
client := surf.NewClient().
Builder().
Impersonate().Chrome().
ForceHTTP3().
Build().
Unwrap()

resp := client.Get("https://cloudflare-quic.com/").Do()
fmt.Println(resp.Ok().Proto) // HTTP/3.0


Декодирование JSON-ответа:
type User struct {
Name string `json:"name"`
Company string `json:"company"`
}

resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
if resp.IsOk() {
var user User
resp.Ok().Body.JSON(&user)
}


Middleware для логирования:
client := surf.NewClient().
Builder().
With(func(resp *surf.Response) error {
fmt.Printf("статус: %d, время: %v\n", resp.StatusCode, resp.Time)
return nil
}).
Build().
Unwrap()


Что ещё умеет

• поддерживает прокси SOCKS5 с UDP для HTTP/3, DNS-over-TLS
• привязку к сетевому интерфейсу
• Unix-сокеты
• кэширование тела ответа
• стриминг, Server-Sent Events

Клиент совместим со стандартным net/http через метод Std() — это позволяет использовать его с любыми сторонними библиотеками, ожидающими *http.Client.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍9👾2
😊 Топ-вакансий для Go-разработчиков за неделю

Golang-разработчик (eHealth) — до 200 000 ₽, удаленно по Москве

Middle+ Software Engineer — удаленно + помогут с переездом

Tech Lead / Senior Backend Developer (Golang) — до 4 000 $ , удалёнка вне РФ и РБ

➡️ Еще больше топовых вакансий — в нашем канале Go jobs

🐸 Библиотека Go-разработчика

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
📘 На новой платформе Mentorix вышел курс — «Golang: микросервисная архитектура и проектирование API»

Уже пишете на Go и хотите вырасти из «закрыть тикет ручкой» в архитектора распределённых систем? Этот курс — именно про инженерию: как спроектировать API, развернуть и держать в продакшене десяток сервисов, которые не падают под нагрузкой.

• Полный стек: HTTP/REST, gRPC, RabbitMQ и Kafka, PostgreSQL, Redis, Docker, Kubernetes, Prometheus + Grafana
• 200+ интерактивных заданий с автопроверкой — пишете код прямо в браузере, в любое удобное время
• Финальный проект: рабочая микросервисная экосистема, которую кладёте в портфолио и показываете на собесе

🎓 Сертификат по завершении — добавьте его в резюме или профиль LinkedIn

Скидка 40% — действует 48 часов

🚀 Прокачайте Go и выйдите на уровень мидл/сеньор-разработчика микросервисов. Начните сегодня — следующая неделя будет уже с новыми навыками.

👉 Пройти курс на Mentorix
1
👩‍💻 git reset vs git revert: когда что использовать

Оба инструмента отменяют изменения, но делают это по-разному. Путаница между ними приводит к потере коммитов или конфликтам в общей ветке.

Что делает git reset

git reset перемещает указатель ветки назад. Он буквально переписывает историю коммитов — те коммиты, которые были после указанной точки, исчезают.

Три режима работы:

git reset --soft HEAD~1 — отменяет коммит, но сохраняет изменения в индексе. Файлы готовы к новому коммиту.

git reset --mixed HEAD~1 — отменяет коммит и убирает файлы из индекса. Изменения остаются в рабочей директории. Это режим по умолчанию.

git reset --hard HEAD~1 — удаляет коммит и все изменения без возможности восстановления.

Пример: написали коммит с опечаткой в сообщении или забыли добавить файл.
git reset --soft HEAD~1
git add forgotten-file.js
git commit -m "правильное сообщение"


Что делает git revert

git revert создаёт новый коммит, который отменяет изменения из указанного коммита. История не переписывается — в ней появляется дополнительная запись об отмене.

git revert a1b2c3d


Git создаст коммит вида Revert "название вашего коммита". В нём будут обратные изменения — то, что было добавлено, удалится, и наоборот.

Если нужно отменить несколько коммитов подряд:
git revert HEAD~3..HEAD


В чём принципиальная разница

git reset меняет историю. Если вы уже отправили ветку на сервер и потом сделали reset, вам придётся делать git push --force. Это создаёт проблемы для всех, кто работает с этой веткой — их локальные копии окажутся не синхронизированы с удалённой.

git revert историю не трогает. Новый коммит просто добавляется поверх. Это безопасно для общих веток.

Как выбрать

Работаете в локальной ветке, которую ещё не пушили — используйте git reset. Он чище, не засоряет историю лишними коммитами.

Нужно отменить изменения в ветке, с которой работает команда — только git revert. Даже если очень хочется сделать reset и force push, это плохая идея.

Что делать, если всё сломалось

Если случайно сделали git reset --hard и потеряли коммиты — не паникуйте. Git хранит ссылки на все объекты в reflog ещё 30 дней.
git reflog
git reset --hard HEAD@{2}


reflog покажет историю всех перемещений HEAD. Найдите нужный коммит и восстановитесь на него.

git reset — для локальной правки истории до того, как она ушла на сервер. git revert — для безопасной отмены в общих ветках. Правило простое: если ветка уже запушена и её видят другие, используйте revert.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7