# GIT

# Как удалить историю GIT

### 1. **Создайте новый начальный коммит:**

- Переключитесь на новую ветку без истории:  
    `bash git checkout --orphan new-branch`
- Добавьте все файлы в новый коммит:  
    `bash git add -A`
- Создайте начальный коммит:  
    `bash git commit -m "Начальный коммит"`

---

### 2. **Удалите старую ветку `main`:**

- Удалите текущую ветку `main`:  
    `bash git branch -D main`

---

### 3. **Переименуйте новую ветку в `main`:**

- Переименуйте новую ветку (`new-branch`) в `main`:  
    `bash git branch -m main`

---

### 4. **Принудительно отправьте изменения в удаленный репозиторий:**

- Принудительно замените историю в удаленном репозитории:  
    `bash git push -f origin main`

---

### 5. **Очистите локальный репозиторий (опционально):**

Если вы хотите очистить локальный репозиторий от старой истории, выполните:

```bash
   git reflog expire --expire=now --all
   git gc --prune=now --aggressive
```

---

### 6. **Обновите локальный репозиторий (если необходимо):**

Если у вас есть другие клоны репозитория, обновите их:

```bash
   git fetch --all
   git reset --hard origin/main
```

---

### Важно:

- **Это действие необратимо**: после удаления истории коммитов восстановить их будет невозможно.
- **Уведомите коллег**: если вы работаете в команде, убедитесь, что все участники знают о предстоящих изменениях, так как это может повлиять на их локальные репозитории.

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

# Как откатить последний коммит

Инструкция для отката последнего коммита, в зависимости от ситуации.

---

## 1. Откат последнего коммита без публикации

Если коммит ещё **не был отправлен** в удалённый репозиторий:

- Удалить коммит, сохранив изменения в индексе (стадии):
    
    ```bash
    git reset --soft HEAD~1
    
    ```
- Удалить коммит и убрать изменения из индекса, оставив их в рабочей папке:
    
    ```bash
    git reset --mixed HEAD~1
    
    ```
- Удалить коммит и изменения полностью (⚠️ безвозвратно):
    
    ```bash
    git reset --hard HEAD~1
    
    ```

---

## 2. Откат опубликованного коммита (без изменения истории)

Если коммит уже **отправлен в удалённый репозиторий**:

- Создать новый коммит, который отменяет изменения предыдущего: 
    
    ```bash
    git revert HEAD
    ```

После этого отправить изменения в репозиторий:

```bash
git push
```

---

## 3. Жёсткий откат опубликованного коммита (с изменением истории)

Если нужно полностью удалить коммит (и изменения), и ты готов "переписать" историю репозитория:

- Удалить последний коммит и изменения:
    
    ```bash
    git reset --hard HEAD~1
    ```
- Принудительно отправить изменения:
    
    ```bash
    git push --force
    ```

⚠️ **Предупреждение:** Этот способ может привести к проблемам для других разработчиков, так как история репозитория будет изменена.

---

### Вывод

Выбирай способ в зависимости от ситуации: для локальных коммитов подойдут `reset`, для опубликованных — безопасный `revert` или жёсткий `reset --hard`. Если есть сомнения, уточни детали своей задачи!

# Полное слияние ветки test в main с удалением test

## 📌 Задача

У вас есть две ветки: `main` и `test`. Вам нужно:

- **Полностью заменить содержимое `main` на текущее состояние `test`**.
- **Удалить ветку `test` после слияния**.

---

## ✅ Пошаговое решение

### 1️⃣ **Переключаемся в `main`**

```bash
git checkout main
```

### 2️⃣ **Обновляем `main` перед слиянием** (если работаем с удалённым репозиторием)

```bash
git pull origin main
```

### 3️⃣ **Полностью заменяем `main` на `test`**

```bash
git reset --hard test
```

### 4️⃣ **Принудительно отправляем изменения в удалённый репозиторий**

```bash
git push --force origin main
```

🚨 **Внимание!** Использование `--force` полностью заменит удалённую ветку `main` на состояние `test`. Будьте уверены, что ничего важного не потеряете!

### 5️⃣ **Удаляем ветку `test` локально**

```bash
git branch -D test

```

### 6️⃣ **Удаляем ветку `test` на удалённом сервере**

```bash
git push origin --delete test
```

---

## 🔥 Объяснение команд

<table id="bkmrk-%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-git"><thead><tr><th>Команда</th><th>Описание</th></tr></thead><tbody><tr><td><code>git checkout main</code></td><td>Переключаемся в ветку <code>main</code>.</td></tr><tr><td><code>git pull origin main</code></td><td>Загружаем актуальные изменения <code>main</code>.</td></tr><tr><td><code>git reset &#45;&#45;hard test</code></td><td>Полностью заменяем содержимое <code>main</code> на <code>test</code>.</td></tr><tr><td><code>git push &#45;&#45;force origin main</code></td><td>Принудительно обновляем <code>main</code> на удалённом сервере.</td></tr><tr><td><code>git branch &#45;D test</code></td><td>Удаляем локальную ветку <code>test</code>.</td></tr><tr><td><code>git push origin &#45;&#45;delete test</code></td><td>Удаляем ветку <code>test</code> в удалённом репозитории.</td></tr></tbody></table>

---

## 🚀 Итог

- Ветка **`main` станет идентичной `test`**.
- Ветка **`test` будет удалена локально и на сервере**.

---

## ⚠ Важно!

- **Если `main` используется другими разработчиками**, предупредите их перед выполнением `git push --force origin main`, так как это **перезапишет всю историю**.
- **Более безопасный способ**, если `main` нельзя перезаписывать принудительно: 
    
    ```bash
    git checkout main
    git merge --strategy=ours test
    git push origin main
    ```

# Процесс разработки и интеграции изменений в основную ветку

Процесс разработки и интеграции изменений в основную ветку (`main` или `master`) в GIT обычно включает несколько этапов. Описание ниже основано на стандартном Git Flow, но может адаптироваться под конкретные требования.

---

## **1. Планирование и создание задачи**

Прежде чем приступить к разработке, необходимо:

- Определить задачу (например, новую фичу, исправление бага, рефакторинг).
- Завести тикет в системе управления задачами (Jira, YouTrack, GitLab Issues и т.д.).
- Определить, в какой ветке будет вестись работа.

---

## **2. Создание новой ветки**

Разработчик создает новую ветку на основе последней актуальной версии `main`:

```bash
git checkout main
git pull origin main
git checkout -b feature/new-feature
```

Где `feature/new-feature` — имя ветки, соответствующее задаче.

Если работа ведется с багфиксом, может использоваться ветка `bugfix/bug-id`.

---

## **3. Разработка и коммиты**

Разработчик пишет код, делает изменения и фиксирует их:

```bash
git add .
git commit -m "Добавлена новая функциональность"
```

Рекомендуется делать осмысленные коммиты и использовать семантические сообщения (`fix:`, `feat:`, `refactor:`, `docs:`, `test:`).

---

## **4. Локальное тестирование**

Перед отправкой изменений важно:

- Запустить юнит-тесты.
- Протестировать код в рабочем окружении (локальном, dev).
- Убедиться, что не нарушена работа других модулей.

---

## **5. Отправка изменений в удаленный репозиторий**

После завершения работы над задачей:

```bash
git push origin feature/new-feature
```

Создается **Merge Request (Pull Request)** в GitLab/GitHub.

---

## **6. Код-ревью**

- Коллеги проверяют код, дают замечания.
- Разработчик вносит правки, дополняет тестами (если нужно).
- Повторяет `git push` до окончательного одобрения.

---

## **7. Интеграция в основную ветку**

После успешного ревью:

- Ветка `feature/new-feature` вливается в `develop` (или сразу в `main`, если процесс без `develop`).
- Используется `merge` или `rebase` (в зависимости от стратегии проекта): 
    
    ```bash
    git checkout main
    git pull origin main
    git merge feature/new-feature
    git push origin main
    ```
- В некоторых случаях может использоваться **Squash &amp; Merge** для объединения коммитов.

---

## **8. Автоматизация через CI/CD**

После слияния в `main` могут автоматически запускаться:

- Автоматические тесты.
- Деплой на тестовый или production сервер (в зависимости от настроек CI/CD).

---

## **9. Удаление ненужных веток**

После успешного слияния:

```bash
git branch -d feature/new-feature
git push origin --delete feature/new-feature
```

Это помогает поддерживать чистоту репозитория.

---

## **10. Деплой и релиз**

Если проект использует версионирование:

- Генерируется новая версия (`git tag v1.2.3`).
- Запускается CI/CD пайплайн, который деплоит код.

---

### **Итог**

Этот процесс помогает обеспечить стабильность разработки, контроль качества и чистоту репозитория. В реальных проектах могут быть добавлены дополнительные этапы, например, работа с `hotfix`-ветками, релизными ветками (`release/`), более строгий контроль тестирования и деплоя.

# Переключение на другую задачу, когда текущая еще не закончена

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

---

## **1. Использование `git stash` (Временное сохранение изменений)**

Если изменения не готовы для коммита, можно их временно отложить:

```bash
git stash
```

Теперь рабочая директория станет чистой, и можно переключаться на другую ветку:

```bash
git checkout feature/another-task
```

Когда будет возможность вернуться к предыдущей задаче, можно восстановить изменения:

```bash
git checkout feature/new-feature
git stash pop  # Вернет изменения и удалит их из stash
```

Если требуется сохранить несколько отложенных изменений, можно посмотреть список stash:

```bash
git stash list
```

А затем применить нужный:

```bash
git stash apply stash@{0}
```

---

## **2. Коммит незавершенных изменений в черновую ветку**

Если изменения значительные, но не готовы для основного репозитория, можно создать временную ветку:

```bash
git checkout -b wip/feature-new-feature
git add .
git commit -m "WIP: временное сохранение"
git push origin wip/feature-new-feature
```

После этого можно переключиться на другую задачу:

```bash
git checkout feature/another-task
```

Когда будет возможность вернуться, просто переключиться обратно:

```bash
git checkout feature/new-feature
git merge wip/feature-new-feature
```

---

## **3. Коммит с пометкой `WIP` (Work In Progress)**

Если возможно закоммитить частичные изменения, можно сделать коммит с пометкой `WIP`:

```bash
git add .
git commit -m "WIP: начало работы над фичей"
```

Затем переключиться на другую ветку:

```bash
git checkout feature/another-task
```

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

---

### **Какой способ выбрать?**

- **`git stash`** — если изменения локальные и их не нужно пушить.
- **Черновая ветка (`wip/feature-new-feature`)** — если требуется сохранить изменения на сервере.
- **Коммит `WIP`** — если можно сделать осмысленный коммит.

Обычно в командах `git stash` подходит для быстрого переключения, а `WIP`-коммиты или черновые ветки — для более долгосрочных перерывов.

# Squash & Merge в Git или сохранение истории коммитов без промежуточных записей

**Squash &amp; Merge** — это способ слияния изменений, при котором несколько коммитов объединяются (squash — "сжимать") в один перед вливанием в основную ветку. Этот метод позволяет сохранить чистую историю коммитов без лишних промежуточных записей.

---

### **Как работает Squash &amp; Merge?**

Допустим, в ветке `feature/new-feature` есть несколько коммитов:

```
commit a1b2c3d - Fix bug in query handler
commit d4e5f6g - Add logging
commit h7i8j9k - Implement new feature
commit l0m1n2o - Fix typo in previous commit
```

При обычном `merge` они просто добавятся в основную ветку (`main`).

Но если использовать **Squash &amp; Merge**, все эти коммиты объединяются в один:

```
commit p9q8r7s - Implement new feature and fixes
```

Таким образом, история остается чистой.

---

### **Когда использовать Squash &amp; Merge?**

✅ **Когда нужно объединить "мусорные" коммиты** (например, тестовые исправления, исправления опечаток).  
✅ **Когда код писался в несколько итераций**, но результат — одно логическое изменение.  
✅ **При работе в feature-ветках**, чтобы в `main` попадали только готовые коммиты.  
❌ **Не подходит для веток, где важна детальная история коммитов** (например, в `develop` или `release`).

---

### **Как выполнить Squash &amp; Merge?**

#### **1. Вручную через `git rebase -i`**

Переключаемся на нужную ветку:

```bash
git checkout feature/new-feature
```

Запускаем интерактивный rebase:

```bash
git rebase -i main
```

Git покажет список коммитов, например:

```
pick a1b2c3d Fix bug in query handler
pick d4e5f6g Add logging
pick h7i8j9k Implement new feature
pick l0m1n2o Fix typo in previous commit
```

Заменяем `pick` на `squash (s)` у всех коммитов, кроме первого:

```
pick a1b2c3d Fix bug in query handler
squash d4e5f6g Add logging
squash h7i8j9k Implement new feature
squash l0m1n2o Fix typo in previous commit
```

После сохранения Git предложит изменить сообщение коммита, оставляем итоговое.

Затем пушим изменения (если уже был push в удаленный репозиторий, потребуется `--force`):

```bash
git push origin feature/new-feature --force
```

---

#### **2. Через GitHub/GitLab UI**

При слиянии Pull Request (Merge Request) можно выбрать опцию **Squash &amp; Merge**:

- В **GitHub**: `Merge pull request -> Squash & Merge`
- В **GitLab**: `Merge Request -> Squash commits`

---

### **Вывод**

Squash &amp; Merge удобен для поддержания чистоты истории коммитов. Важно применять его осознанно: если детальная история не нужна, squash поможет убрать ненужные коммиты и оставить только финальные изменения.

# Варианты размещения конфигурационных файлов GIT

## 📁 Где Git ищет конфиги (Windows)

Git использует три уровня конфигурации, **в жёстко заданном порядке**:

<div class="_tableContainer_16hzy_1" id="bkmrk-%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C-%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0-%D0%A4%D0%B0%D0%B9%D0%BB"><div class="_tableWrapper_16hzy_14 group flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)"><thead><tr><th>Уровень</th><th>Команда</th><th>Файл по умолчанию</th></tr></thead><tbody><tr><td>**System**</td><td><code>git config &#45;&#45;system</code></td><td><code>C&#58;&#92;Program Files&#92;Git&#92;etc&#92;gitconfig</code></td></tr><tr><td>**Global**</td><td><code>git config &#45;&#45;global</code></td><td><code>&#37;USERPROFILE&#37;&#92;&#46;gitconfig</code></td></tr><tr><td>**Local**</td><td><code>git config &#45;&#45;local</code> (по умолчанию)</td><td><code>&#60;путь&#95;к&#95;проекту&#62;&#92;&#46;git&#92;config</code></td></tr></tbody></table>

</div></div>---

## 🔍 Как Git находит `C:\Program Files\Git\etc\gitconfig`

Git встроенно знает путь к своему системному конфигу:

- Этот путь **жёстко прошит в бинарный Git for Windows**
- Он **не переопределяется**
- Используется **для установки глобальных параметров по умолчанию**, например:
    
    ```
    [credential] helper = store
    ```
    
    или
    
    ```
    [core] autocrlf = true
    ```

---

## 🧼 Можно ли его изменить?

📌 **Нет — стандартный путь `etc/gitconfig` не переопределяется в переменных окружения.**

Однако ты можешь:

2. Открыть его вручную:
    
    ```
    notepad "C:\Program Files\Git\etc\gitconfig"
    ```
3. Удалить или закомментировать ненужные строки:
    
    ```
    [credential] helper = store ; ← закомментировать
    ```

> ⚠️ Требуются права администратора.

---

## ✅ Альтернатива: переопределить в глобальной/локальной конфигурации

Если ты не хочешь трогать системный файл, просто **переопредели**:

```
git config --global credential.helper ""
```

или

```
git config --local credential.helper "store --file=.git/.git-credentials"
```

Git будет использовать **наиболее приоритетный из найденных** (local &gt; global &gt; system).

# Project Access Token (PAT)

## 🔍 Кто может видеть токен?

- **Сразу после создания** токен можно скопировать **один раз**.
- **Все пользователи с правами Maintainer/Owner** проекта **могут видеть, что токен существует**, но **не видят его значение**.
- **Ты мог видеть его под другим пользователем**, только если:
    
    
    - ты смотришь в список активных токенов,
    - но **не можешь использовать его**, если не скопировал ранее его значение.

---

## 👤 Для кого работает Project Access Token?

Токен **работает от имени "виртуального пользователя" проекта**:

- В GitLab в списке пользователей он отображается как:  
    `Project access token (имя_токена)`  
    и имеет отдельный ID

🔐 **Он не зависит от логина, под которым ты залогинен в GitLab UI или Git**.

---

## 🧠 Как узнать, к какому пользователю "привязан" Project Access Token?

> ❗ Он **не привязан к реальному пользователю**. Он:

- создаётся **в рамках проекта**
- действует **в рамках прав, которые ты задал при создании** (например, `api`, `read_repository`, `write_repository`)
- фигурирует как "сервисный пользователь" проекта

---

## 🔐 Кто может использовать этот токен?

Любой, у кого есть:

- **Сам токен (строка)**,
- **И URL проекта**, к которому он относится.

📌 Поэтому **сам токен нужно хранить безопасно**, как обычный пароль.

---

## ✅ Как использовать:

```
# Формат для .git-credentials: https://<token_name>:<access_token>@gitlab.example.com
```

<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%3A"><div class="overflow-y-auto p-4" dir="ltr">Пример:</div><div class="overflow-y-auto p-4" dir="ltr"></div></div>

```
https://ci-bot:glpat-abc123@gitlab.example.com/group/project.git
```

---

## 🔐 Вывод:

<div class="_tableContainer_16hzy_1" id="bkmrk-%D0%92%D0%BE%D0%BF%D1%80%D0%BE%D1%81-%D0%9E%D1%82%D0%B2%D0%B5%D1%82-%D0%9A%D1%82%D0%BE-%D0%B2%D0%B8%D0%B4"><div class="_tableWrapper_16hzy_14 group flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)"><thead><tr><th>Вопрос</th><th>Ответ</th></tr></thead><tbody><tr><td>Кто видит токен?</td><td>Только в момент создания — и владельцы с правами Maintainer в проекте</td></tr><tr><td>Кому принадлежит?</td><td>Проекту, не пользователю</td></tr><tr><td>Кто может использовать?</td><td>Любой, у кого есть значение токена</td></tr><tr><td>Где отображается?</td><td>В настройках проекта → Access Tokens</td></tr><tr><td>Можно ли узнать, кто создал?</td><td>Нет, GitLab не отображает автора токена</td></tr></tbody></table>

<div class="sticky end-(--thread-content-margin) h-0 self-end select-none"><div class="absolute end-0 flex items-end"></div></div></div></div>

# Замена пользователя и email во всех коммитах

# Массовая замена имени и email в истории Git-репозитория

## 1. Проверить всех авторов и их email

```sh
git log --format='%an <%ae>' | sort
```

*Выведет список всех уникальных авторов и их email. Используйте этот список, чтобы убедиться, что все нужные данные попадут под замену.*

---

## 2. Замена имени и email во всех коммитах (через callback)

```sh
python -m git_filter_repo --name-callback "return b'New Name'" --email-callback "return b'new@email.com'" --force
```

- `New Name` — новое имя автора и коммиттера.
- `new@email.com` — новый email.
- `--force` — требуется для работы не на свежем клоне.

**Пример:**

```sh
python -m git_filter_repo --name-callback "return b'John Doe'" --email-callback "return b'john.doe@example.com'" --force
```

---

## 3. Добавить ссылку на удалённый репозиторий

Данный пункт необходим, т.к. после выполнения git\_filter\_repo связь с удаленным репозиторием удаляется.

```sh
git remote add origin https://github.com/yourname/yourrepo.git
```

*Замените на свой адрес удалённого репозитория.*

---

## 4. Форсированная отправка истории в удалённый репозиторий

```sh
git push --force origin main
```

- Если основная ветка называется иначе, подставьте нужное имя (например, `master`).

---

## Установка `git-filter-repo`

### Через pip (универсально, нужен Python):

```sh
pip install git-filter-repo
```

### Через Homebrew (macOS):

```sh
brew install git-filter-repo
```

### Проверка установки:

```sh
python -m git_filter_repo --help
```

Если появилась справка — всё готово.

---

## Замена только определённых email/имён через файл mailmap

### 1. Создать файл `my-mailmap.txt` со строками замены:

```
New Name <new@email.com> <old@email1.com>
New Name <new@email.com> <old@email2.com>
```

### 2. Выполнить фильтрацию:

```sh
python -m git_filter_repo --mailmap my-mailmap.txt --force
```

---

## Важно!

- После переписывания истории используйте только `git push --force`.
- Все, кто работал с этим репозиторием, должны сделать новый клон или жёсткий reset.
- Рекомендуется всегда работать на свежем клоне, чтобы не потерять старые данные.

# Удаление и управление тегами в Git

Ниже описаны основные команды для удаления тегов в Git и различия между лёгкими и аннотированными тегами.

---

## Удаление тегов

### 1. Локальное удаление тега

```bash
git tag -d v0.1.0
```

**Что делает**

- Удаляет локальную метку (тег) с именем `v0.1.0` из вашего репозитория.

**Как это работает “под капотом”**

1. Git хранит теги как файлы в каталоге `.git/refs/tags/`.
2. Команда удаляет файл:

```
   .git/refs/tags/v0.1.0
```

3. История коммитов не меняется, просто исчезает локальный указатель `v0.1.0`.

**Пример вывода**

```bash
$ git tag -d v0.1.0
Deleted tag 'v0.1.0' (was a1b2c3d)
```

Где `a1b2c3d` — SHA-1 коммита, на который указывал удалённый тег.

---

### 2. Удаление тега на удалённом сервере

```bash
git push --delete origin v0.1.0
```

**Что делает**

- Удаляет тег `v0.1.0` на удалённом репозитории `origin`.

**Как это работает “под капотом”**

1. Git преобразует команду в удалённый запрос удаления рефа:

```
   :refs/tags/v0.1.0
```

2. Отправляет запрос на сервер `origin`, где удаляется файл `refs/tags/v0.1.0`.
3. При последующем `git fetch` или новом клонировании этот тег больше не будет виден.

**Пример вывода**

```bash
$ git push --delete origin v0.1.0
To git@github.com:yourname/your-repo.git
 - [deleted]         v0.1.0
```

---

### 3. Полный сценарий: удаление и перевыпуск тега

```bash
# 1. Локально удаляем старый тег
git tag -d v0.1.0

# 2. Удаляем его на удалённом сервере
git push --delete origin v0.1.0

# 3. (Опционально) Создаём новый тег на другом коммите
git tag -a v0.1.0 -m "Release version 0.1.0"

# 4. Пушим новый тег на сервер
git push origin v0.1.0
```

---

## Типы тегов в Git

В Git существуют два основных вида тегов:

1. **Лёгкие (lightweight) теги**
2. **Аннотированные (annotated) теги**

---

### Лёгкий тег (`git tag v0.1.0`)

```bash
git tag v0.1.0
```

- Ярлык (символьная ссылка) на указанный коммит (по умолчанию на `HEAD`).
- Не создаёт отдельного объекта в хранилище Git.
- Не содержит метаданных (автор, дата, сообщение).
- Используется для быстрых личных “закладок”.

---

### Аннотированный тег

```bash
git tag -a v0.1.0 -m "Release version 0.1.0"
```

- Создаёт объект типа `tag` в `.git/objects/…`.
- Сохраняет: 
    - Имя автора (tagger) и дату создания.
    - Текстовое сообщение описания.
    - (Опционально) PGP-подпись (`git tag -s …`).
- Рекомендуется для официальных релизов.

---

### Сравнительная таблица

<table id="bkmrk-%D0%A5%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0-%D0%9B%D1%91%D0%B3%D0%BA%D0%B8"><thead><tr><th id="bkmrk-%D0%A5%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0">Характеристика</th><th id="bkmrk-%D0%9B%D1%91%D0%B3%D0%BA%D0%B8%D0%B9-%D1%82%D0%B5%D0%B3">Лёгкий тег</th><th id="bkmrk-%D0%90%D0%BD%D0%BD%D0%BE%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9-%D1%82%D0%B5%D0%B3-1">Аннотированный тег</th></tr></thead><tbody><tr><td>Объект в базе данных</td><td>Отсутствует</td><td>Присутствует (тип <code>tag</code>)</td></tr><tr><td>Метаданные (автор, дата)</td><td>Нет</td><td>Да</td></tr><tr><td>Сообщение</td><td>Нет</td><td>Да (через <code>&#45;m</code>)</td></tr><tr><td>Возможность GPG-подписи</td><td>Нет</td><td>Да (ключ <code>&#45;s</code>)</td></tr><tr><td>Вывод <code>git show &#60;tag&#62;</code></td><td>Показывает сразу коммит</td><td>Сначала показывает данные тега, затем коммит</td></tr></tbody></table>

---

### Итог

- **`git tag v0.1.0`** — лёгкий, простой указатель без описания и метаданных.
- **`git tag -a v0.1.0 -m "…"`** — документированная, полнофункциональная и (опционально) подписанная метка, идеальная для релизов.

# Git: Изменение последнего коммита

## <a id="bkmrk-"></a>Команда

```
git commit --amend -m "новое сообщение коммита"

```

## <a id="bkmrk--1"></a>Описание

Команда `git commit --amend` позволяет изменить **последний коммит** в Git.  
С её помощью можно:

- заменить сообщение коммита;
- добавить или убрать файлы из последнего коммита;
- исправить изменения без создания нового коммита.

В данном примере изменяется только **сообщение**.  
Флаг `-m` указывает новый текст комментария.

## <a id="bkmrk--2"></a>Важно

- Используйте `--amend` только для коммитов, которые **ещё не отправлены в удалённый репозиторий** (`git push`).
- Если коммит уже опубликован, изменение потребует `git push --force`, что может повлиять на других разработчиков.

## <a id="bkmrk--3"></a>Примеры

### <a id="bkmrk--4"></a>Изменить только сообщение

```
git commit --amend -m "исправлен текст комментария"

```

### <a id="bkmrk--5"></a>Добавить забытые файлы и изменить сообщение

```
git add forgotten_file.txt
git commit --amend -m "добавлен недостающий файл"

```

---

👉 Используйте `git commit --amend` для аккуратных правок в истории.