Отмена коммита в Git с помощью git revert

17 декабря 2025
Автор

Олег Марков

Введение

Отмена коммита в Git может казаться простой задачей, пока не сталкиваешься с реальным командным проектом, удалённым репозиторием и ветками, которые уже ушли в прод. В этот момент становится важно не просто "откатить изменения", а сделать это безопасно, не ломая историю и не мешая работе остальных разработчиков.

Здесь на первый план выходит команда git revert. С её помощью вы можете отменить любой коммит, при этом не переписывая историю, а аккуратно добавляя новый коммит, который "обнуляет" изменения предыдущего. Это поведение особенно полезно в командной работе, где переписывание истории часто недопустимо.

В статье вы увидите, как работает git revert, в чём его отличие от git reset, в каких ситуациях его стоит использовать, а когда лучше выбрать другие инструменты. Мы пошагово разберём типичные сценарии, посмотрим, как работать с конфликтами при revert, и затронем расширенные приёмы, которые пригодятся в реальных проектах.

Что такое git revert и как он работает

Логическая идея git revert

Сначала давайте разберёмся на концептуальном уровне, что именно делает git revert.

Git хранит историю в виде цепочки коммитов. Каждый коммит фиксирует набор изменений по сравнению с предыдущим состоянием. Когда вы выполняете git revert для конкретного коммита, Git:

  1. Берёт отличия, которые внёс этот коммит.
  2. Строит обратные изменения (инверсный diff).
  3. Создаёт новый коммит, который применяет эту "обратную разницу" к текущему состоянию ветки.

В результате исходный коммит остаётся в истории, но его влияние на код отменяется последующим коммитом. История остаётся линейной и непротиворечивой, а все участники видят, что именно произошло.

Смотрите, я покажу вам это на простой визуализации.

Предположим, у вас была такая цепочка:

  • A – базовый коммит
  • B – добавляет функцию
  • C – добавляет тесты

История:

A → B → C

Теперь вы делаете git revert для коммита B:

  • Git создаёт новый коммит D, который отменяет изменения из B.

Новая история:

A → B → C → D

Коммит B по-прежнему есть в истории, но его изменения уже не действуют, потому что поверх них появился D, который всё "откручивает" назад.

Ключевые особенности git revert

Кратко выделим основные свойства git revert:

  • Не переписывает историю, а добавляет новый коммит.
  • Безопасен для уже опубликованных веток (которые вы пушили в общий репозиторий).
  • Может применяться к любому коммиту, а не только к последнему.
  • Может вызывать конфликты, если код сильно изменился после того коммита.
  • Часто выступает "стандартным" способом отмены в командной разработке.

Теперь давайте перейдём к практическому использованию.

Базовый синтаксис и первый пример

Простой revert последнего коммита

Самая простая форма использования:

git revert HEAD
# HEAD - это указатель на последний коммит в текущей ветке

После выполнения этой команды Git:

  1. Сгенерирует новый коммит.
  2. Откроет ваш редактор для ввода сообщения (по умолчанию).
  3. Сохранит коммит с текстом вида: Revert "Сообщение исходного коммита"

Если вы хотите задать сообщение коммита сразу, можно использовать флаг -m в случае merge-коммитов или изменить текст по умолчанию в открывшемся редакторе.

Давайте разберём пример.

Предположим, вы добавили файл:

echo "version 1" > app.txt
git add app.txt
git commit -m "Добавлен файл app.txt"

Потом вы случайно изменили его не так, как нужно:

echo "broken version" > app.txt
git add app.txt
git commit -m "Неверное изменение файла"

Теперь история такая:

  • Коммит 1: Добавлен файл app.txt
  • Коммит 2: Неверное изменение файла

Вы понимаете, что второй коммит нужно отменить:

git revert HEAD
# Отменяем последний коммит

Git создаст новый коммит:

  • Коммит 3: Revert "Неверное изменение файла"

И вернёт содержимое app.txt к состоянию из первого коммита.

Revert конкретного коммита по хэшу

В реальных проектах вам часто понадобится откатить не последний коммит, а один из предыдущих. Для этого используется хэш коммита.

Посмотрите, как это делается:

git log --oneline
# 7f3a9c2 Добавлен новый API эндпоинт
# 1b5e4a7 Исправлена ошибка в авторизации
# a2c9d31 Рефакторинг модуля аутентификации

Допустим, вы хотите отменить "Исправлена ошибка в авторизации":

git revert 1b5e4a7
# 1b5e4a7 - первые символы хэша коммита

Git:

  • вычислит изменения, внесённые именно этим коммитом,
  • попробует "вычесть" их из текущего состояния,
  • создаст новый коммит, который отменит эту часть истории.

Важно понимать: всё, что произошло после этого коммита, сохраняется. Именно поэтому revert часто называют "отменой по логике, а не по времени".

git revert против git reset – в чём разница и когда что использовать

Коротко о git reset

git reset изменяет указатель ветки и (опционально) состояние рабочей директории и индекса, как будто некоторых коммитов не было.

Если вы сделаете:

git reset --hard HEAD~1
# Перемещаем указатель на один коммит назад
# HEAD~1 - родитель последнего коммита

То:

  • последний коммит исчезнет из ветки,
  • изменения из него будут потеряны (при варианте --hard),
  • история ветки перепишется.

Это удобно, если вы ещё не пушили изменения и работаете один.

Главное отличие с точки зрения истории

Давайте сопоставим:

Использование git reset

История до:

A → B → C (HEAD указывает на C)

Команда:

git reset --hard B

История ветки после:

A → B (C больше не виден в этой ветке)

Коммит C как объект в Git ещё существует какое-то время, но в истории ветки он уже не фигурирует. Если кто-то другой успел забрать этот коммит из удалённого репозитория, начнутся расхождения истории.

Использование git revert

Та же начальная история:

A → B → C (HEAD указывает на C)

Команда:

git revert C

История после:

A → B → C → D

Где D – новый коммит, который отменяет изменения из C. Никакие старые коммиты не исчезают.

Когда использовать git revert, а когда git reset

Посмотрите на практические рекомендации:

git revert выбирайте, когда:

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

git reset удобно применять, когда:

  • вы работаете в своей локальной ветке, которую ещё не пушили;
  • хотите просто "выкинуть" неудачные коммиты из истории;
  • нужно подготовить "чистую" историю перед созданием merge request (иногда так делают с rebase + reset).

Хорошее практическое правило:
если коммит уже ушёл в удалённый репозиторий и его мог кто-то забрать – используйте git revert.

Пошаговая инструкция – типичные сценарии использования

Отмена последнего коммита без конфликтов

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

Шаги:

  1. Проверить журнал:

    git log --oneline -n 3
    # 8c5f40b Неверный фикс
    # 3b7284c Добавлены проверки
    # 1f92aaf Начальная версия
    
  2. Убедиться, что хотите отменить именно последний коммит "Неверный фикс".

  3. Выполнить:

    git revert HEAD
    # Отменяем последний коммит
    
  4. Git откроет редактор сообщения коммита. Вы можете:

    • оставить текст по умолчанию,
    • изменить на более осмысленный, например:
      Отмена неверного фикса валидации.
  5. Сохранить и выйти из редактора.

  6. Проверить результат:

    git log --oneline -n 4
    # 9d6a1f3 Отмена неверного фикса валидации
    # 8c5f40b Неверный фикс
    # 3b7284c Добавлены проверки
    # 1f92aaf Начальная версия
    

Теперь смотрите, вы можете проверить содержимое файлов, чтобы убедиться, что состояние вернулось к корректному.

Отмена нескольких коммитов по одному

Иногда вы понимаете, что серия последних коммитов была неудачной. В таком случае логика простая – делать несколько revert.

Например, у вас есть:

git log --oneline -n 5
# e80cfe2 Оптимизация запросов к БД
# 70a8c1c Добавлены индексы
# 77f0eb1 Рефакторинг DAO
# 4b22a31 Добавлен модуль статистики
# 8ff3f1d Базовая структура проекта

Предположим, вы хотите отменить три последних коммита.

Один из вариантов:

git revert HEAD       # Отмена e80cfe2
git revert HEAD~1     # Отмена 70a8c1c
git revert HEAD~2     # Отмена 77f0eb1 (учитывая, что новые revert-коммиты добавились сверху)

Но такой подход может запутать, потому что после первого revert история меняется. Надежнее указывать точные хэши:

git revert e80cfe2
git revert 70a8c1c
git revert 77f0eb1

Так вы явно говорите Git, какие именно коммиты нужно "обратить", независимо от того, какие новые коммиты уже появились.

Отмена серии коммитов одним диапазоном

Git позволяет отменить несколько последовательных коммитов одной командой.

Смотрите, как это делается:

git log --oneline -n 6
# 9b12e8d Добавлен новый отчёт
# a7b0f64 Поправлена фильтрация отчёта
# d41f6c0 Правки стилей отчёта
# 4f5ac82 Обновлён UI панели
# 2a8ff23 Исправлена авторизация
# 0a1b2c3 Начальный коммит

Теперь вы хотите отменить три коммита, связанные с отчётом:

  • 9b12e8d
  • a7b0f64
  • d41f6c0

Можно сделать:

git revert d41f6c0^..9b12e8d
# d41f6c0^ - родитель первого коммита диапазона
# 9b12e8d   - последний коммит диапазона

Git создаст по одному "revert-коммиту" на каждый из указанных коммитов в правильном порядке, чтобы изменения корректно отменились.

Если в процессе возникнут конфликты, вам придётся их разрешать последовательно для каждого генерируемого коммита.

Отмена изменений без создания коммита сразу

Иногда вам нужно просто вернуть файлы в состояние до определённого коммита, но вы пока не готовы фиксировать результат. Здесь можно использовать флаг --no-commit (сокращение -n).

Пример:

git revert --no-commit 1b5e4a7
# Изменения для отмены попадают в индекс и рабочую директорию
# Но новый коммит еще не создается

Дальше вы можете:

  • подредактировать файлы вручную,
  • убрать часть изменений из индекса, если что-то нужно сохранить,
  • затем создать коммит:
git commit -m "Частичная отмена изменений из 1b5e4a7"

Этот подход удобен, когда вы хотите использовать git revert как "шаблон изменений", но всё равно планируете слегка скорректировать результат перед фиксацией.

Работа с конфликтами при git revert

Почему возникают конфликты

Конфликты при git revert возникают по тем же причинам, что и при обычном merge или rebase: Git не может автоматически совместить изменения.

Давайте посмотрим, как это может выглядеть.

Представим, что:

  1. В коммите X вы добавили строку в функцию.
  2. В последующих коммитах эту же функцию серьёзно переписали.

Теперь вы делаете git revert X. Git пытается "достать" из истории изменения из коммита X и применить обратную версию к текущему коду. Но код уже сильно изменился, и Git не понимает, куда именно эти изменения нужно "открутить".

Отсюда – конфликт.

Типичный сценарий с конфликтом

Предположим, у вас был такой коммит:

git show X
# Псевдокод
# - func Calculate() {
# -     return 10
# - }
# + func Calculate() {
# +     return 20
# + }

Позже функция была переписана:

// Версия в актуальном коде
func Calculate() int {
    // Здесь уже сложная логика и никакого "20"
    result := expensiveOperation()
    return result
}

Теперь вы запускаете:

git revert X

Git пытается вернуть return 10 вместо return 20, но в текущем файле ни одного из этих вариантов уже нет – поэтому он не знает, как совместить изменения.

Разрешение конфликта на практике

При конфликте Git:

  1. Остановит процесс revert.
  2. Пометит конфликтующие файлы специальными маркерами.
  3. Выведет список файлов в статусе "both modified".

Дальше ваши шаги:

  1. Посмотреть статус:

    git status
    # on branch feature
    # you are currently reverting commit X
    # unmerged paths:
    #   both modified: path/to/file.go
    
  2. Открыть конфликтующий файл и найти блоки вида:

    // Здесь я размещаю пример, чтобы вам было проще понять
    func Calculate() int {
    <<<<<<< HEAD
        // Текущая версия функции
        result := expensiveOperation()
        return result
    =======
        // Версия, которая должна быть "отменена" (инвертированное изменение)
        return 10
    >>>>>>> parent of X... сообщение коммита
    }
    
  3. Вручную выбрать нужный вариант или написать новый код, который соответствует вашей цели. Обычно при revert вы хотите сохранить актуальную бизнес-логику, но убрать последствия конкретного старого изменения.

  4. Удалить маркеры конфликтов (<<<<<<<, =======, >>>>>>>).

  5. Добавить файл в индекс:

    git add path/to/file.go
    
  6. Продолжить revert:

    git revert --continue
    # Git завершит создание revert-коммита
    

Если вы решите отменить процесс и не делать revert, можно выполнить:

git revert --abort
# Откатит состояние к тому моменту, когда вы запустили git revert

Обратите внимание, что при работе с конфликтами очень помогает хорошее понимание того, какие именно изменения вы хотите "вычесть" из текущей истории.

Особые случаи: revert merge-коммитов

В чём сложность с merge-коммитами

Merge-коммиты объединяют несколько веток. У них несколько родителей (обычно два). Когда вы делаете git revert для merge-коммита, Git не всегда однозначно понимает, какие изменения нужно считать "внесёнными этим merge" и что именно нужно "откатить".

Для решения этой проблемы используется флаг -m (или --mainline), который указывает, какого родителя считать "основной линией" истории.

Пример с merge-коммитом

Представьте, у вас была ветка main и ветка feature, и вы их смёрджили:

git checkout main
git merge feature
# Получен merge-коммит M

История:

  • на main: A → B → M
  • на feature: A → C → D → (входит в M)

Теперь вы хотите отменить этот merge-коммит M, то есть вернуть ветку main в состояние, как будто feature никогда не вливалась.

Команда будет выглядеть так:

git revert -m 1 M
# -m 1 означает - считать первого родителя "основной веткой"

Комментарии:

  • Родитель 1 – это обычно та ветка, в которую вы вливались (main).
  • Родитель 2 – ветка, которая вливалась (feature).

Git вычисляет, какие изменения пришли из второго родителя по сравнению с первым, и создаёт коммит, который эти изменения "вычитает".

Как узнать, кто из родителей кто

Чтобы увидеть родителей merge-коммита, используйте:

git show M
# В начале вывода будет что-то вроде:
# commit M (HEAD -> main)
# Merge: <hash_parent1> <hash_parent2>
# Author: ...
# Date: ...

Обычно:

  • <hash_parent1> – это текущая ветка (main),
  • <hash_parent2> – влившаяся ветка (feature).

Если ситуация сложнее (например, несколько merge подряд), лучше явно посмотреть граф:

git log --graph --oneline --decorate

Здесь вы увидите, откуда пришли ветки и как они сливались.

Опасности revert merge-коммитов

Отмена merge-коммитов может сделать дальнейшие слияния с той же веткой запутанными. Например, после revert merge-коммита Git может считать, что изменения из feature уже учтены, и не предложит их повторно при следующем merge, или наоборот – создаст много конфликтов.

Перед тем как делать git revert для merge-коммита, полезно:

  • обсудить это с командой,
  • понять, не проще ли откатить отдельные коммиты из feature ветки,
  • или сделать revert конкретных коммитов, которые вызвали проблему.

Практические советы и типичные паттерны использования

Использование git revert в продакшен-процессах

Частый сценарий: выкатили релиз, обнаружили критический баг. Нужно быстро откатить проблемное изменение и при этом сохранить прозрачную историю.

Обычно процесс выглядит так:

  1. Найти проблемный коммит по логам или по истории merge request.
  2. Выполнить git revert в ветке, которая деплоится в прод (часто это main или release).
  3. Запустить новый деплой с revert-коммитом.
  4. Позже, в отдельной ветке, спокойно исправить проблему и сделать нормальный фикс.

Такой подход:

  • оставляет в истории отметку, что конкретное изменение было отменено;
  • позволяет связать тикеты в баг-трекере с конкретными revert-коммитами;
  • делает релизную историю предсказуемой.

Комбинация revert и cherry-pick

Иногда нужно:

  • в одной ветке отменить изменение,
  • а в другой – сохранить.

Например, вы сделали фичу в ветке feature, затем смёрджили её в main, но выяснилось, что в проде она проблемная. Однако в будущей версии (в ветке develop) вы хотите сохранить её, чтобы доработать.

Возможная схема:

  1. В ветке main сделать:

    git revert <hash_фичи_или_merge-коммита>
    
  2. В ветке develop ничего не откатывать, а продолжать доработку.

Если же вы случайно сделали revert в той ветке, где хотел оставить изменения, их можно вернуть обратно через git cherry-pick исходного коммита (который вы ранее отменили). Но важно понимать, что это создаст новый коммит с теми же изменениями, а не "отменит отмену" на уровне ссылок.

Как не "ломать голову" над revert через месяц

Полезная практика: давать осмысленные сообщения revert-коммитам.

Вместо:

  • Revert "Fix bug in cart"

Лучше написать что-то более контекстное:

  • Отмена фикса корзины из-за регресса в оплате
  • Revert фикса корзины - сломана интеграция с платежами

Так через месяц (или для других членов команды) будет очевидно, почему именно изменения были отменены.

Также удобно в описании revert-коммита указывать:

  • ссылку на тикет в трекере,
  • ссылку на merge request,
  • краткое объяснение, что именно пошло не так.

Частые ошибки при использовании git revert

Попытка использовать revert вместо reset для "чистки" локальной истории

Иногда разработчики, опасаясь reset, начинают делать revert даже для локальных черновых коммитов, которые ещё никто не видел. В итоге локальная история засоряется лишними "revert-коммитами", которые не несут ценности.

Если вы:

  • работаете в своей ветке,
  • ещё не пушили изменения,
  • хотите просто убрать неудачные коммиты,

то в большинстве случаев логичнее использовать git reset (или интерактивный rebase), а не revert.

Непонимание, что revert не "удаляет" коммит

После git revert исходный коммит по-прежнему есть в истории. Это значит, что:

  • код из него может "вернуться" при неосторожных манипуляциях (например, при cherry-pick старых коммитов);
  • при анализе истории нужно учитывать и оригинальные, и revert-коммиты.

Чтобы увидеть полную картину, хорошо помогает просмотр истории с графом и фильтрацией по файлам.

Revert "revert-коммита" и двойная отмена

Иногда возникает следующая ситуация:

  1. Вы сделали коммит с изменением.
  2. Позже его отменили через git revert.
  3. Ещё позже решили, что всё-таки то изменение нужно вернуть.

В таком случае можно:

  • либо заново применить те же изменения вручную,
  • либо сделать revert "revert-коммита".

То есть, если у вас есть:

  • A – исходный коммит,
  • BRevert "A",

то команда:

git revert B

создаст новый коммит C, который отменит отмену, и фактически вернёт изменения из A обратно. Это нормальная практика, но в истории нужно уметь читать такую "двойную инверсию".

Хороший рабочий процесс с git revert в команде

Согласованные правила в проекте

В командных репозиториях часто принимают правила:

  • В общих ветках (main, develop, release) не использовать git reset и не переписывать историю.
  • Для отмены изменений в таких ветках использовать только git revert.
  • Любые "грязные" манипуляции с историей проводить только в личных фичевых ветках до момента ревью.

Такие правила снижают риск конфликтов при pull/push и избавляют команду от сложных "расхождений" истории.

Отмена проблемного merge через revert вместо force push

Покажу вам распространённый анти-паттерн:

  1. Ветка main обновилась merge-коммитом, который сломал прод.
  2. Кто-то решает "просто откатить ветку назад" через:

    git reset --hard <старый_коммит>
    git push --force
    
  3. В результате:

    • история main переписывается,
    • все, кто успел забрать новый merge-коммит, получают расхождение истории,
    • начинается череда конфликтов и путаницы.

Лучший вариант в такой ситуации:

git revert <hash_merge-коммита> -m 1
git push

Так вы:

  • сохраните историю,
  • явно покажете, что проблемный merge был отменён,
  • избежите проблем с чужими локальными копиями.

Документирование отмен

Полезная практика – сопровождать revert:

  • ссылкой на инцидент (если был аварийный случай),
  • кратким описанием последствий,
  • пояснением, что планируется сделать дальше (например, "доработать и выкатить позже в версии 1.2").

Так из истории Git можно будет понять не только "что отменили", но и "зачем и к чему это привело".

Заключение

git revert – это базовый инструмент для безопасной отмены изменений в Git, особенно в командных и продакшен-сценариях. Он не переписывает историю, а аккуратно добавляет новый коммит, который "вычитает" эффект заданного коммита. Благодаря этому история остаётся прозрачной, а совместная работа – предсказуемой.

Ключевые моменты, которые важно запомнить:

  • Используйте git revert для опубликованных веток и общего репозитория.
  • Не путайте revert и reset – это разные по смыслу операции.
  • Будьте готовы к конфликтам при revert старых коммитов и merge-коммитов, и умейте их разрешать.
  • Оставляйте осмысленные сообщения revert-коммитам – это поможет вам и вашей команде через время понять причины отмены.

Если вы будете осознанно выбирать между git revert и другими командами Git, процесс отката изменений перестанет быть чем-то рискованным и станет обычной частью рабочего процесса.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Как отменить git revert если я ошибся и отменил не тот коммит

Если вы только что сделали git revert и поняли, что отменили не тот коммит, самый простой вариант – отменить сам revert. Есть два подхода:

  1. Если вы ещё не пушили revert-коммит и работаете в своей ветке:

    git reset --hard HEAD~1
    # Убираем последний revert-коммит из истории ветки
    

    Важно – все изменения из последнего коммита будут потеряны.

  2. Если revert уже опубликован и reset использовать нельзя – сделайте "обратный revert":

    git log --oneline
    # Найдите hash revert-коммита
    git revert <hash_revert-коммита>
    # Новый коммит вернёт изменения обратно
    

Можно ли сделать git revert только для части файлов из коммита

Напрямую git revert так не умеет, но можно использовать комбинацию с флагом --no-commit:

  1. Примените revert без коммита: bash git revert --no-commit <hash_коммита>
  2. Откройте список изменённых файлов: bash git status
  3. Уберите из индекса те файлы, которые не хотите включать в отмену: bash git restore --staged path/to/file1 path/to/file2 # Или git reset path/to/file1
  4. При необходимости подкорректируйте оставшиеся файлы вручную.
  5. Зафиксируйте коммит: bash git commit -m "Частичная отмена изменений из <hash>"

Что делать если git revert говорит что коммит уже был отменен

Обычно это сообщение вида "The revert was already done". Оно появляется, если:

  • вы пытаетесь сделать revert для коммита, который уже "обнулён" другим revert-коммитом;
  • или если цепочка изменений такова, что итоговый diff равен нулю.

Проверить это можно так:

git log --grep="<hash_или_сообщение_коммита>"
# Или просмотрите историю вручную

Если коммит уже был отменён, повторный revert не нужен. Если же вы хотите вернуть изменения, которые когда-то были отменены, найдите хэш revert-коммита и сделайте:

git revert <hash_revert-коммита>
# Это "отменит отмену" и вернёт изменения

Как откатить изменения коммита только в одном файле без revert всего коммита

Для этого подойдёт команда git checkout (в новых версиях git restore) с указанием коммита и файла:

# Вернуть файл к состоянию до определенного коммита
git checkout <hash_родителя_коммита> -- path/to/file

# В новых версиях:
git restore --source=<hash_родителя_коммита> path/to/file

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


Как проверить что именно отменит git revert перед выполнением команды

Вы можете посмотреть diff, который будет применён при revert, с помощью команды git show:

git show <hash_коммита>
# Покажет изменения, которые внёс коммит

# Чтобы представить "обратный" diff, можно мысленно инвертировать +/-,
# но удобнее сделать так:
git diff <hash_коммита>^ <hash_коммита>
# Это тот же diff, который revert попытается "вычесть" из текущего состояния

Если хотите оценить последствия ближе к текущему состоянию, можно применить revert с --no-commit:

git revert --no-commit <hash>
# Посмотреть изменения через git diff
git diff
# Если не устраивает - отменить:
git revert --abort
Сброс к состоянию коммита с помощью git reset --hardСтрелочка вправо

Постройте личный план изучения Git до уровня Middle — бесплатно!

Git — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Git

Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы Git

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий