Git is a distributed version control system that allows developers to track changes in their code using a series of snapshots, stored in a database called the repository.
Key features of Git include:
- distributed - every developer has a copy of the repository
- history - every change is tracked
- collaboration - multiple developers can work on the same project
- safety - all changes are tracked, can be undone or recovered
In order to better understand Git, I strongly recommend the use of Git command line interface.
Key steps to not forget after installing and configuring Git:
- Set up your editor - vim is the default editor, but if you want to change it:
git config --global core.editor "vim"git config --global core.editor "nano"git config --global core.editor "code --wait"
- End of line - set the end of line character:
- linux and mac -
git config --global core.autocrlf input - windows -
git config --global core.autocrlf true
- linux and mac -
- Use GPG - Sign your commits for extra security.
- Check your configuration -
git config --global -e
Creating commits (snapshots)
#1 Initializing a repository
git init- initializes or re-initializes a new Git repository, which includes creating a .git directory containing subdirectories for objects, refs/heads, refs/tags, and template files. It also establishes an initial branch that has no commits yet.
#2 Basic Git workflow
The fundamental Git workflow is structured around three key components:
- Working Directory: This is where files are actively created, modified, and removed.
- Staging Area: This area serves as a prep zone where files are reviewed before being committed.
- Repository: This component acts as the archive, storing all the snapshots of the project.
When you use git add you are moving files from the working directory to the staging area.
When you use git commit you are moving files from the staging area to the repository.
#3 Writing a commit message
When I write a commit message, I follow these guidelines:
- Short and descriptive - 50 characters or less
- Use the imperative mood - “Fix bug” instead of “Fixed bug” or “Fixes bug”
- Use the body if explanation is needed - 72 characters or less
- Do not end with a period
#4 Common Git commands
Remove files
To remove a file from git you need to remove it from the working directory and add the change to the staging area.
Or you can use the shortcut git rm command to remove the file from both the working directory and the staging area:
git rm <filename>
Rename files
To rename a file in git you need to rename it in the working directory and add the change to the staging area.
Or you can use the shortcut git mv command to rename the file in both the working directory and the staging area:
git mv <old_filename> <new_filename>
Check the status the short way
git status -s
Useful diffs
git diff- shows the difference between the working directory and the staging area.git diff --staged- shows the difference between the staging area and the repository.git diff <commit_hash>- shows the difference between the working directory and the repository.git diff <commit_hash> HEAD- shows the difference between commit and the last commit.git diff <commit1_hash1> <commit2_hash>- shows the difference between two commits.
Looking at the history
git log- shows the history of the repository.git log --oneline- shows the history of the repository in one line.git log --oneline --reverse- shows the history of the repository in one line.git log --stat- shows the history of the repository with statistics.git log --graph- shows the history of the repository with a graph.git log --oneline --patch- shows the history of the repository in one line with the changes.git log --oneline -3- shows the last 3 commits in one line.git log --oneline --author="achilles"- shows the commits by an author in one line.git log --oneline --grep="fix"- show commits with the word “fix” in the message.git log --oneline -S"find" --patch- show commits with the word “find” in the changes.git log --oneline package.json- show commits that changed the package.json file.git log --oneline --all --graph- show the history of all branches with a graph.
Viewing a commit
git show <commit_hash>- shows the commit details.git show <commit_hash> --stat- shows the commit details with statistics.git show <commit_hash> --name-only- shows the commit details with the file names.git show <commit_hash> --name-status- shows the commit details with the file names and status.git show HEAD~2:filename- shows the content of a file in a specific commit.
Look at the tree
git ls-tree HEAD- shows the tree of the repository.git ls-tree HEAD~2- shows the tree of the repository in a specific commit.git ls-tree HEAD~2 -r- shows the tree of the repository in a specific commit recursively.
Un-stage files
git restore --staged <filename>- un-stages a file from the staging area.git restore --staged .- un-stages all files from the staging area.
Discard changes in the working directory
git restore <filename>- discards the changes to a file in the working directory.git restore .- discards all changes in the working directory.git clean -fd- removes untracked files from the working directory.git checkout .- discards all changes in the working directory.
Restore a file to a previous version
git restore <filename>- restores a file to the last commit.git restore <filename> --source <commit_hash>- restores a file to a specific commit.
Format the output
git log --pretty=format:"%Cgreen%an%Creset : %h - %cd".
Setting up aliases
git config --global alias.lg "log --oneline --graph --all".
Checkout a commit
git checkout <commit_hash>- moves the HEAD to a specific commit.git checkout master- moves the HEAD to the master branch.
Check user history
git shortlog- shows the history of the repository by author.git shortlog -s- shows the history of the repository by author with statistics.git shortlog -s -n- shows the history of the repository by author with statistics and sorted by commits.
Check file history
git log --oneline --patch package.json- shows the history of the package.json file.
Restore a deleted file from a commit
git log --oneline -- <filename>- find the commit that deleted the file.git checkout <commit_hash> -- <filename>- restore the file from the commit.
blame
git blame <filename>- shows the history of the file with the author of each line.
Tags
git tag- shows the tags.git tag v1.0 <commit_hash>- creates a tag for a specific commit.git checkout v1.0- moves the HEAD to the tag.git tag -a v1.0 -m "Version 1.0"- creates an annotated tag.git push origin v1.0- pushes the tag to the remote.git push origin --tags- pushes all tags to the remote.git tag -d v1.0- deletes the tag.
Branching
Create a branch
git branch <branch_name>- creates a branch.git checkout -b <branch_name>- creates a branch and moves the HEAD to the branch.git switch -c <branch_name>- creates a branch and moves the HEAD to the branch.git switch <branch_name>- moves the HEAD to the branch.git branch -m <new_branch_name>- renames the branch.
Delete a branch
git branch -d <branch_name>- deletes a branch.git branch -D <branch_name>- deletes a branch even if it has unmerged changes.
Compare branches
git log master..branch- shows the commits in branch that are not in master.git diff master..branch- compares two branches.git diff branch- compares the working directory with the branch.
Stash
git stash- stashes the changes.git stash push -m "message"- stashes the changes with a message.git stash list- shows the list of stashes.git stash show- shows the last stash.git stash apply- applies the last stash.git stash apply stash@{1}- applies a specific stash.git stash pop- applies and drops the last stash.git stash drop- drops the last stash.git stash clear- drops all stashes.
Merge
There are two types of merges:
-
Fast-forward merge: A fast-forward merge in Git happens when you merge branches and Git can just move the pointer of the target branch forward to the same commit that the source branch is pointing to
-
Three-way merge: A three-way merge in Git happens when you merge branches and Git needs to create a new commit to merge the two branches.
-
git merge <branch_name>- merges the branch into the current branch. -
git merge --no-ff <branch_name>- merges the branch into the current branch with a new commit.
See branches
git branch- shows the branches.git branch -v- shows the branches with the last commit.git branch -vv- shows the branches with the last commit and the tracking branch.git branch --merged- shows the branches that are merged.git branch --no-merged- shows the branches that are not merged.git merge --squash <branch_name>- merges the branch into the current branch with a squash commit.
Conflicts
Conflicts occur when two branches have changed the same part of the same file.
- Resolve the conflict: Open the file and resolve the conflict.
- Add the file:
git add <filename>. - Commit the file:
git commit. - Abort the merge:
git merge --abort. - Continue the merge:
git merge --continue.
Undo a merge
git reset --soft ORIG_HEAD- undoes the merge and keeps the changes.git reset --mixed ORIG_HEAD- undoes the merge and keeps the changes in the working directory.git reset --hard ORIG_HEAD- undoes the merge and removes the changes.git revert <commit_hash>- reverts a commit.git revert -m 1 <commit_hash>- reverts a merge commit on the first parent.
Rebase
Rebase is the process of moving or combining a sequence of commits to a new base commit.
- Rebase:
git rebase <branch_name>. - Rebase interactive:
git rebase -i <branch_name>. - Rebase continue:
git rebase --continue. - Rebase abort:
git rebase --abort. - Rebase skip:
git rebase --skip. - Rebase onto:
git rebase --onto <branch_name> <commit_hash>.
Cherry-pick
Cherry-pick is the process of applying a commit from one branch to another.
- Cherry-pick:
git cherry-pick <commit_hash>. - Cherry-pick continue:
git cherry-pick --continue. - Cherry-pick abort:
git cherry-pick --abort. - Cherry-pick edit:
git cherry-pick -e <commit_hash>.
Get a file from another branch
git checkout <branch_name> -- <filename>- gets a file from another branch.git restore --source <branch_name> -- <filename>- gets a file from another branch.
Remotes
git remote- shows the remotes.git remote -v- shows the remotes with the URLs.
Pull
git pull- fetches and merges the changes from the remote.git pull --rebase- fetches and rebases the changes from the remote.
Release
git tag -a v1.0 -m "Version 1.0"- creates a tag for the release.git push origin v1.0- pushes the tag to the remote.
Sharing branches
git push -u origin <branch_name>- push and set the upstream.
Revert multiple commits
git revert <commit1_hash> <commit2_hash>- reverts multiple commits.git revert --no-commit HEAD~3..HEAD- reverts the last 3 commits.git revert --continue- continues the revert.
Recover a lost commit
git reflog- shows the history of the HEAD.git reflog show feature- shows the history of the feature branch.
Amend a commit
git commit --amend- amends the last commit.git commit --amend -m "New message"- amends the last commit with a new message.
Edit an earlier commit
git rebase -i HEAD~3- starts an interactive rebase. Select the commit to edit and change the command to edit.git commit --amend- amends the commit.git rebase --continue- continues the rebase.
Drop an earlier commit
git rebase -i HEAD~3- starts an interactive rebase. Select the commit to drop and remove the line.git rebase --continue- continues the rebase.
Reword an earlier commit
git rebase -i HEAD~3- starts an interactive rebase. Select the commit to reword and change the command to reword.
Reorder commits
git rebase -i HEAD~3- starts an interactive rebase. Reorder the commits.
Squash commits
git rebase -i HEAD~3- starts an interactive rebase. Select the commits to squash/fixup and change the command to squash.
Split a commit
git rebase -i HEAD~3- starts an interactive rebase. Select the commit to edit and change the command to edit.git reset --mixed HEAD^- resets the commit but keeps the changes.git add <filename>- adds the changes.git commit -m "First part"- commits the first part.git add <filename>- adds the changes.git commit -m "Second part"- commits the second part.git rebase --continue- continues the rebase.