> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/02-tools/git/11-git-maintenance.md).

# 11. Git Maintenance

Git is all about commits: you stage commits, create commits, view old commits, and transfer commits between repositories using many different Git commands. The majority of these commands operate on a commit in some form or another, and many of them accept a commit reference as a parameter.

The most direct way to reference a commit is via its SHA-1 hash.

```bash
git log # show commit hashes
git show <object> # displays git object
git rev-parse <branch> # show commit hash for specific branch
```

A **ref** is an indirect way of referring to a commit. You can think of it as a user-friendly alias for a commit hash. This is Git’s internal mechanism of representing branches and tags. Refs are stored as normal text files in the `.git/refs` directory In addition to the refs directory, there are a few special refs that reside in the top-level `.git` directory. They are listed below:

* `HEAD` – The currently checked-out commit/branch.
* `FETCH_HEAD` – The most recently fetched branch from a remote repo.
* `ORIG_HEAD` – A backup reference to HEAD before drastic changes to it.
* `MERGE_HEAD` – The commit(s) that you’re merging into the current branch with git merge.
* `CHERRY_PICK_HEAD` – The commit that you’re cherry-picking.

A **refspec** maps a branch in the local repository to a branch in a remote repository. This makes it possible to manage remote branches using local Git commands and to configure some advanced git push and git fetch behavior. A refspec is specified as `[+]<src>:<dst>`. The `<src>` parameter is the source branch in the local repository, and the `<dst>` parameter is the destination branch in the remote repository.

### `git gc`

The `git gc` command is an important one to remember. It will pack up your objects into the delta-compressed format, saving you a lot of space and seriously speeding up several commands. Garbage collector moves all of the individual branch and tag files in the refs folder into a single file called packed-refs located in the top of the `.git` directory.

If can turn `gc` automatically on and off by setting a configuration setting to `1` or `0`:

```bash
git config --global gc.auto 1
```

This will make git automatically `gc` itself occasionally.

### `git prune` and `git fsck`

If you want to check the health of your repository, you can run `git fsck`, which will tell you if you have any unreachable or corrupted objects in your database and help you fix them. Which you can then remove with `git prune` (you can run it with `-n` first to see what it will do).

### Relative refs

You can also refer to commits relative to another commit

* `~` character lets you reach parent commits. The `~` character will always follow the first parent of a merge commit.
* `^` character will always follow the second parent of a merge commit.

Relative refs can be used with the same commands that a normal ref can be used.

```bash
git show HEAD~2 # grandparent of HEAD
git show HEAD^2 # grandparent of HEAD
git show HEAD^2^1 # possible to combine

git log HEAD^2 # Only list commits that are parent of the second parent of a merge commit
git reset HEAD~3 # Remove the last 3 commits from the current branch
git rebase -i HEAD~3 # Interactively rebase the last 3 commits on the current branch
```

![](/files/-M6fwLa1JDyNBI_2-hLF)

### `git reflog`

Одной из вещей, которую Git делает в фоновом режиме, является ведение журнала ссылок, в котором хранятся ссылки указателей HEAD и веток за последние несколько месяцев. Для просмотра этого журнала используется команда `git reflog`. В виде этой временной истории Git сохраняет данные о каждом изменении вершины ветки.

The `reflog` is Git’s safety net. It records almost every change you make in your repository, regardless of whether you committed a snapshot or not. You can think of it as a chronological history of everything you’ve done in your local repo.

```bash
400e4b7 HEAD@{0}: checkout: moving from master to HEAD~2
0e25143 HEAD@{1}: commit (amend): Integrate some awesome feature into `master`
00f5425 HEAD@{2}: commit (merge): Merge branch ';feature';
ad8621a HEAD@{3}: commit: Finish the feature
```

The `HEAD{<n>}` syntax lets you reference commits stored in the `reflog`. It works a lot like the `HEAD~<n>` references section, but the `<n>` refers to an entry in the `reflog` instead of the commit history. You can use this to revert to a state that would otherwise be lost. For example, lets say you just scrapped a new feature with `git reset`.

```bash
git show HEAD@{5}
git show master@{yesterday}
```

### `git filter-branch`

Команда git filter-branch по заданному шаблону переписывает содержимое коммитов, позволяя, к примеру, полностью удалить файл из истории или извлечь во вложенную папку результаты фильтрации целого репозитория. Например, пользователь случайно в коммиты попал огромный файл, или пароли. Как обычно бывает в подобной ситуации, ее можно использовать только для проектов, которые еще не попали в общий доступ и переписываемые коммиты не служат основой ничьей работы.

### Config

```bash
git config --global pull.rebase true
git config --global branch.autosetuprebase always
```

### Aliases

```bash
git config --global alias.unstage-all 'reset HEAD --'
git config --global alias.unstage 'reset HEAD'
git config --global alias.last 'log -1 HEAD'
git config --global alias.stash-revert '!git stash show -p | git apply -R'
git log --oneline --decorate –graph --all

```
