type | description | use cases |
---|---|---|
feat | introduces a new feature | new code (exclude configuration and fixes) |
fix | fixes a bug | modify exisiting code (exclude configuration) |
chore | includes a technical or preventive maintenance task | modify or add files, enabling a feature flag, upgrade versions, configuration formatting, architecture files, etc |
test | add missing tests or correct existing ones | only for the types of files that follow the test format |
style | changes that do not affect the semantics of the code | related to formatting or cleaning |
Note: If any type commit include a Breaking Change we need to add a bang (!) after the type name.
Example
feat!: my awesome feature broke something
<type>[scope(optional)]: <description> (Max 72 chars per line)
[body(optional)]
[footer(optional)]
Examples
feat[utils]: add schema generator tool
This need to be used from now in all schemas related task
ft @john @camilia
chore: upgrade project version to 2.6.1
TL;DR:
git pull --rebase
instead ofgit pull
to avoid merge commits that result fromgit pull
.git rebase -i @{u}
beforegit push
.- on long-lived feature branch,
git merge master
to make feature compatible with latest master. - on main branch,
git merge --no-ff feature-branch
to ship a feature.
This command rewrites only the local commits which you are about to push. It gives one a chance to perform housekeeping before sharing your changes, such as squashing related commits together and rewriting commit messages.
git rebase -i @{u}
The u
stands for upstream and it resolves to the latest commit on this branch
on the remote.
Working on a long-lived feature branch, it pays off sometimes to merge in the master branch to verify that they are compatible and to get the latest bug fixes.
Rebasing is also an options but could lead to shortcomings:
- Rewriting history on a long lived feature branch with multiple people working on it is hard.
- Merge conflicts can be easier to deal with by merging instead of rebasing (smaller and more conflicts with rebase).
switch
and restore
replace the overloaded checkout
command and make it more explicit.
- create a new branch named
my-new-feature
and switch to it
git switch -c my-new-feature
- detach HEAD state
git switch -d f8c540805b7e16753c65619ca3d7514178353f39
- switch to the
develop
branch
git switch develop
- switch to latest branch
git switch -
- restore staged changes from the index
git restore --staged .
This command implements the behaviour of checkout
when running against a
file. One can restore the state of a file to a specified git revision.
- restore the file
hello.c
to the HEAD state
git restore hello.c
- same as using
git reset
git restore --staged hello.c
- discard all files in the current directory
git restore .
- restore the file
index.js
from themaster
branch
git restore --source master index.js
- Remove hunks interactively from the worktree
# All files
git checkout -p
# Only filename
git checkout -p filename
- Add hunks interactively from the worktree
git add -p
- Squash last 5 commits
git rebase -i HEAD~5
- Preview git stash
git stash show -p
- Stash files that are not in the index
git stash --keep-index
- Initialize git submodules
git submodule update --init --recursive
- Reset the git history of a repo
## Remove the history from
rm -rf .git
## recreate the repos from the current content only
git init
git add .
git commit -m "Initial commit"
## push to the github remote repos ensuring you overwrite history
git remote add origin git@github.com:<YOUR ACCOUNT>/<YOUR REPOS>.git
git push -u --force origin master
- Add signing key to git
$ gpg --list-keys --keyid-format long
$ git config --global commit.gpgsign true
$ git config --global user.signingkey <KEYID>
- When committing add the -S flag
git commit -S -m "your commit message"
- Get one file from another branch - filename.txt from feature1 branch
git checkout feature1 -- filename.txt
- git reset
# Same as git reset --mixed HEAD
git reset
# --soft: only commit history
# --mixed: staged snapshot and commit history
# --hard: working directory and staged snapshot and commit history
- git revert
# Changes to be reverted BCD
A <-- B <-- C <-- D
# Solution 1
git revert --no-commit D
git revert --no-commit C
git revert --no-commit B
git commit -m "the commit message"
# Solution 2 - assuming the branch is `feature`
# The beginning of the range is exclusive
git revert feature~3..feature
# Solution 3
git revert --no-commit HEAD~3..
- git log - 3 most recent commits
git log -3
- git log - by date
git log --after="2019-1-1"
git log --after="yesterday"
git log --after="2014-7-1" --before="2014-7-4"
- git log - by author
git log --author="Chouffe"
- git log - by message
git log --grep="JRA-224:"
- git log - by file
git log -- foo.py bar.py
- git log - by content
git log -S"Hello, World!"
- Browse git stashes
tig stash
- List all files that were changed in the branch
git diff --name-only "$(git merge-base master HEAD)"
- Find the 10 files taking up the most space in the repo
git ls-files | xargs ls -l | sort -nrk5 | head -n 10
- Prevent from pushing to master
#!/bin/bash
# .git/hooks/pre-push
# chmod +x .git/hooks/pre-push
protected_branch='master'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [ $protected_branch = $current_branch ]
then
read -p "You're about to push master, is that what you intended? [y|n] " -n 1 -r < /dev/tty
echo
if echo $REPLY | grep -E '^[Yy]$' > /dev/null
then
exit 0 # push will execute
fi
exit 1 # push will not execute
else
exit 0 # push will execute
fi
A repository is a collection of commits, each of which is an archive of what the project’s working tree looked like at a past date, whether on your machine or someone else’s. It also defines HEAD (see below), which identifies the branch or commit the current working tree stemmed from. Lastly, it contains a set of branches and tags, to identify certain commits by name.
Unlike other, similar tools you may have used, Git does not commit changes directly from the working tree into the repository. Instead, changes are first registered in something called the index. Think of it as a way of “confirming” your changes, one by one, before doing a commit (which records all your approved changes at once). Some find it helpful to call it instead as the “staging area”, instead of the index.
A working tree is any directory on your filesystem which has a repository associated with it (typically indicated by the presence of a sub-directory within it named .git.). It includes all the files and sub-directories in that directory.
A commit is a snapshot of your working tree at some point in time. The state of HEAD (see below) at the time your commit is made becomes that commit’s parent. This is what creates the notion of a “revision history”.
A branch is just a name for a commit (and much more will be said about commits in a moment), also called a reference. It’s the parentage of a commit which defines its history, and thus the typical notion of a “branch of development”.
A tag is also a name for a commit, similar to a branch, except that it always names the same commit, and can have its own description text.
The mainline of development in most repositories is done on a branch called “master”. Although this is a typical default, it is in no way special.
HEAD is used by your repository to define what is currently checked out.
Git is a Content-addressabe filesystem: A simple key-value store.
- Git Internals Git Objects
- Git from the inside out
- Git from the bottom up
- Git clone in Haskell
- I haskell a Git
Corresponds to inodes or file contents.
It solves the problem of storing the filename and group files together. A single tree object contains one or more tree entries, each of which contains a sha-1 pointer to a blob or a subtree with its associated mode, type and filename.
Eg.
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
It specifies the top level tree for the snapshot of the project, author and commiter information.
Eg.
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
Hash any content
git hash-object
Hash from --stdin and store it with -w
echo 'hello world' | git hash-object -w --stdin
Hash from filepath and store it with -w
git hash-object -w test.txt
Cat pretty printed object:
git cat-file -p <sha1>
Object directory is located at .git/objects
Return object type of any object
git cat-file -t <sha1>
- sed in git grep
git sed old-value new-value
- Undo the last N commit - moving them to the staging area
git undo # Undo the last commit and add changes to staging
git undo N # Undo N commits
- Completely remove a file from the repository
git obliterate filename
- Does a hard reset and deletes all untracked files from the working directory, including those in .gitignore.
git clear
- Add an entry into gitignore
git gitignore DS_Store
- Diff with current merged master
git diff `git merge-base master HEAD`
- Prevent pushing to master
git config --local branch.master.pushRemote no_push
- Install Git LFS
sudo apt-get install git-lfs
git lfs install
- Clone repo without LFS objects
GIT_LFS_SKIP_SMUDGE=1 git clone REPO_URL
- List lfs files in a repo
git lfs ls-files
- Invalidate the local LFS cache
git lfs prune
- Migrate a file to LFS
git lfs migrate import --yes --no-rewrite "<your-file>"