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.

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:

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.

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

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.

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.

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

git filter-branch

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

Config

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

Aliases

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

Last updated