This is a handy resource that helps to take a fast and overall view of Git and its important abilities. Hope to enjoy!
- Install
- Initializing
- Config
- Save the process
- Inspecting a repository
- Remote Working
- Branches
- Tags
- Undoing Changes
- Rewriting history
If you want to start your work through cloning the project from a remote repository, the clone is needed Otherwise you should initialize your repo locally with init command:
git init <project-name>git clone <remote-repo-url>Before using the git you need to configure some values. The git config command is a convenience function that is used to set Git configuration values on different levels:
-
local: Is the level which is specific to the repository. By default, git config will write to a local level if no configuration option is passed
-
system: Covers an entire user, entire machine and all repos.
-
global: Global level configuration is user-specific, meaning it is applied to an operating system user. The below code shows how we can set name and email for author in global level:
git config --global user.email <[email protected]> git config --global user.name <your-username>
Default name of local repo is Master but you can change it if you want:
git config --global init.defaultBranch <name>
Another helpful config that you can set is the editor. When you are working with git, some commands and situations need to change or define some things. In this case, the request will open with vim by default but it is customizable. The below code shows how we can change the default editor from vim to vs-code:
git config --global core.editor "code --wait"and this config will set nano as prefer editor:
git config --global core.editor "nano"to check current settings, -l is the way:
git config -l
Here you learn how we can transfer changes from working to the stage and finally to the local repo. But before it you should know we can always check the last status with git status:
git status-
Working -> Stage: if you want to transfer special file from working to stage you should note the name of file after add. But there is another option and we can transfer all files with dot. See the example:
git add <file-name> git add .
-
Stage -> Repository: transfer from the stage to the local repository will operational with commit:
git commit -m "commit-message"With -m we can define a short message for our commit but if you want to add longer message you can use commit without any switch and then write your message in the opened editor:
git commit
-
Working -> Repository: it is possible to send changes from working to local-repo directly:
git commit -am "commit-message" -
Working -> Stash: git stash temporarily shelves (or stashes) changes you've made to your working copy so you can work on something else, and then come back and re-apply them later on. Stashing is handy if you need to quickly switch context and work on something else, but you're mid-way through a code change and aren't quite ready to commit.
The below code shows how we can stash, view the stash list, restore the stashed changes, and delete all stashes:git stash save "message" git stash list git stash apply <hash> git stash clear
-
git log: this command is used to view the history of committed changes within a Git repository. These examples show how we can use git log in rare cases or specify with some special switches:
git log git log --oneline git log --oneline --graph git log --oneline --graph --all
The Git log can be filtered in a variety of ways, such as restricting number of commits displayed, filtering by date range, commit author, commit message content, commit ID range, and more. So these filters help us to search in history and find needed data. The fantastic note is we can combine multi filters to specify data with high accuracy:
git log --after="2021-1-1" --before="2022-5-1" --author="name"
git log --grep="refactor"It is often needed to pull a range of commits for review. This can be accomplished utilizing the .. operator, along with the ref names for the start commit and end commit in the range. The ref names can be tags, hashes, or references:
git log <hash>..HEAD
-
git diff: diffing is a function that takes two input data sets and outputs the changes between them. git diff is a multi-use Git command that when executed runs a diff function on Git data sources. These data sources can be commits, branches, files and more. By default git diff will show you any uncommitted changes since the last commit.
Below example show how we can check diff between Working & Stage, Stage & Repository, and Working & Repository:git diff git diff --staged git diff HEAD
It's also possible to get a list of files that has been changed in a particular commit:
git diff-tree <hash>
-
git show: a surprising amount of developers that have been using Git for a while don't know about the Git Show commands. They know that for a shared repository, they can go on GitHub to look at the commit. But it's really easy to do it from the command line too. You don't have to open a browser and click around. If we want to show what files are changed in the commit, we can use git show:
git show <commit or tag>
-
git blame: The git blame command is used to examine the contents of a file line by line and see when each line was last modified and who the author of the modifications:
git blame <file-name>
-
Add remote repo: the git remote command lets you create, view, and delete connections to other repositories. Remote connections are more like bookmarks rather than direct links into other repositories. Instead of providing real-time access to another repository, they serve as convenient names that can be used to reference a not-so-convenient URL:
git remote add <origin> <url>
-
Pull: The git pull command is used to fetch and download content from a remote repository and immediately update the local repository to match that content. So it is combined of git fetch and git merge:
git pull <origin>
-
Fetch: git fetch really only downloads new data from a remote repository, but it doesn't integrate any of this new data into your working files. It's clear when there is any conflict between local and remote, pull will fail and we should fetch the data and make some decisions:
git fetch <origin>
There are two solutions in conflict cases:
- git reset --HARD < hash > : if you want to rollback changes on local and match local with remote.
- git merge < branch >: if your choice is local-repo and want to update remote based on local changes.
-
Push: the git push command is used to upload local repository content to a remote repository:
git push <origin> <main>
A branch represents an independent line of development. Branches serve as an abstraction for the edit/stage/commit process. You can think of them as a way to request a brand new working directory, staging area, and project history. New commits are recorded in the history for the current branch, which results in a fork in the history of the project.
The git branch command lets you create, list, rename, and delete branches. It doesn’t let you switch between branches or put a forked history back together again. For this reason, git branch is tightly integrated with the git checkout and git merge commands.
-
Switch between branch:
git checkout <branch-name>
-
Create branch:
git checkout <branch-name> git branch <new-name>
Creating a branch from a specific commit:
git log git branch <branch-name> <hash>
-
Rename branch:
git checkout <branch-name> git branch -m <new-name>
-
Delete branch:
git branch -d <branch-name>
-
Merge branches: for example merge develop into master:
git checkout master git merge develop
Git Tags are specific reference points in the Git history. Git tags are used to capture the specific point in the history that is further used to point to a released version. A tag does not change like a branch. They don't have a further history of commits after being created. Most people use this feature to mark some release points like (v1.0,…v4.0, and so on)
-
Define tags:
git tag "tag-name" <commit>
git tag -a -m "message" "tag-name" <commit>
-
Push tags: Git tags do not push to the remote repository with branch pushing, So if you tag a commit you should push it separately to the remote server:
git push <origin> --tag
The git reset, git checkout, and git revert commands are all similar in that they undo some type of change in your repository. But, they all affect different combinations of the working directory, staged snapshot, and commit history.
-
Checkout: with checkout, we can switch between commits, branches, etc and review the past.
git checkout <commit> git checkout <branch-name>
-
Restore: You can discard untracked changes and restore it as what is in the stage area:
git restore . -
Revert: When you use the Revert command, the selected commit will copy to the end of the way. So the history will not change but a copy of the selected commit will add to the end as the last commit:
git revert <commit>
-
Reset: git reset takes us back in time and deletes every commit the ahead. so it is like backing to the past! whit customizing the git reset you can select what happens to the files.
--soft deletes commits and send files to stage, --mixed deletes commit and stages and send resources to working, and --hard deletes all of themgit reset --soft <commit> git reset --mixed <commit> git reset --hard <commit>
-
Reflog: you can think about reflog like ctrl+z in windows and redo after undo! git reflog is an amazing resource for recovering project history. You can recover almost anything—anything you’ve committed—via the reflog. Suppose you made some commits, did a git reset --hard to “undo” those changes, and then realized: you want those changes back! Our in another scenario you has been deleted a branch and want to back it again and all this similar scenarios will resolve with help of reflog:
git reflog
After entering the above code, the history will show and we can pick our preferred hash and use reset to roll back things as what was in that special time. In deleted branch scenario we can re-make the branch by passing the hash of the removed branch to the git branch:
git reset <reflog-ref>
git branch <branch-name> <reflog-ref>
Git has several mechanisms for storing history and saving changes. These mechanisms include: Commit --amend, git rebase and git reflog.
Note: Avoid amending or rebasing a commit that other developers have based their work on. This is a confusing situation for developers to be in and it’s complicated to recover from.
-
Amend: amend commits are actually entirely new commits and the previous commit will no longer be on your current branch.
Change the last commit message:
git commit --amend -m "new-message"Add new staged files to the previous commit:
git commit --amend --no-edit
-
Rebase: Rebase has two different modes: standard and interactive.
-
standard mode: when you use the standard rebase, it will re-write the commit history. For example, to update your branch feature with your default branch (here, using main):
git checkout feature git rebase main
Let's compare between merge and standard rebase. Suppose we have two different branches and want to join them toughener. One solution is to use git merge. Just a new commit will register on the main branch and after deleting the sub-brach the history of main + the merge commit will remain. But if we use standard rebase, the commit of the sub-branch will copy at the start of the main branch and the commit of the main will transfer to the end without creating any new message.
-
interactive rebase: This command offers some special functionality that helps us to do many things with histories such as combining, changing messages and etc. For using these tools you should define the start of the way by inputting the hash of the interested commit and then you can work on the commit after that. An editor will open automatically and you should change pick to matching request for hashes follow the help that will show to you on the editor and save the changes
git rebase -i <hash>
-
-
Clear all commit history: This code will delete all commit history by creating a new branch, moving all files to this branch, deleting the main branch, and finally renaming the temp branch to the main.
Note: if your main branch has a different name you should use it instead of main in the below codesgit checkout --orphan temp git commit -m "commit message" git branch -D main git branch -m main git push -f origin main