What is git?
Git is a distributed version control system for managing source code.
So what is version control? Simply put, version control is a system for tracking changes to files. As you modify files, the version control system records and saves each change. This allows you to restore a previous version of your code at any time.
Without a version control system, you are likely stuck manually saving multiple versions of your file using different dates and/or names (e.g. 12-02-2016-monkey_code.php; 12-03-2016-monkey_code.php). This method is time-consuming and impractical when you are dealing with hundreds of files.
It also fails to provide readers with any context as to what changes were made or who they were made by. When multiple team members work on the same file, overwriting can quickly become a problem, and it’s often difficult to keep track of which file is the latest version.
And so we turn to version control systems to solve all of these problems (and more.) With Git, you can easily access your source code’s revision history and track changes. You can see how the version has changed over time and who has made the changes. Because the latest version of a file is stored on a shared repository, Git can prevent unintentional overwrites by anyone on your team who has an older version of the file.
In short, a version control system like Git makes it easy to:
- Keep track of code history
- Collaborate on code as a team
- See who made which changes
- Deploy code to staging or production
There are three main components of a Git project:
- Working tree
The repository, or repo, is the “container” that tracks the changes to your project files. It holds all of the commits — a snapshot of all your files at a point in time — that have been made. You can access the commit history with the Git log.
The working tree, or working directory, consists of files that you are currently working on. You can think of a working tree as a file system where you can view and modify files.
The index, or staging area, is where commits are prepared. The index compares the files in the working tree to the files in the repo. When you make a change in the working tree, the index marks the file as modified before it is committed.
You can think of this as your basic Git workflow:
- Modify your files in the working tree.
- Stage the changes you want to include in the next commit.
- Commit your changes. (Committing will take the files from the index and store them as a snapshot in the repository.)
Three states of Git files
As you can probably guess from the Git workflow, files can be in one of three states:
When you modify a file, the change will only be found in the working tree. You must then stage the changes if you want to include them in your next commit. Once you finish staging all files, you can commit them and add a message describing what you changed. The modified files will then be safely stored in the repo.
Creating a repository
After installing Git on your machine, the first thing you’ll need to do is set up a repository. A repository (i.e., repo) is a centrally located folder for storing all of your code. Once you create a Git repository with your files and directories, you can start tracking changes and versions. In this section, you’ll learn how to get a repository up and running.
Remote repositories and local repositories
There are two types of Git repositories: remote and local.
- A remote repository is hosted on a remote, or off-site, server that is shared among multiple team members.
- A local repository is hosted on a local machine for an individual user.
While you can take advantage of Git version control features with a local repository, collaboration features — like pulling and pushing code changes with teammates — will be better suited on a remote repository.
Ways to create a repository
There are two ways to create a local repository on your machine: you can create a new repository from scratch using a file folder on your computer, or you can clone an existing repository.
You can create a new repo from scratch using the git init command. It can be used to introduce Git into an existing, unversioned project so that you can start tracking changes.
You can copy a remote repository onto your local machine using the git clone command. By default, git clone will automatically set up a local master branch that tracks the remote master branch it was cloned from.
A cloned repository has the same history log as the original one. You can refer and backtrack to any of those commits within your local repository.
Ready to set up a repo for yourself? Follow our step-by-step tutorial to create your first Git repo.
Git does not automatically save every change you make. You must tell Git which changes you want to be recorded by staging those changes. After staging, you can then commit the changes so that they are recorded in the repo.
As mentioned in the Git workflow section, the working tree is where you make changes. There you can edit files, add new files, and remove files that are no longer needed.
Once a file has been changed in the working tree, it is noted as modified in the index (e.g., the staging area where new commits are prepared) where it sits between the repository and the working tree.
Changes made in the working tree are not saved directly to the repository. All changes are first staged in the index and then saved in the repo. Only the files in the index are committed to the repo.
The git commit command lets you record file changes in the repository’s Git history.
Every change you commit will be viewable in the respective file or directory in chronological order.
A 40-character checksum hash uniquely identifies each commit. You can use the checksum hash to retrieve the status or changes that were made on the given commit in your repository.
Separating different types of changes such as bug fixes, new features, and improvements into different sets of commits will allow you and your team members to understand why and how those changes were made easily.
When committing your changes, you are required to enter a commit message. The commit message should accurately describe the changes you’re making.
Make commit messages easy to understand for all your team members. We recommending trying the following structure:
1st line: Abstract of the contents changed by commits 2nd line: Blank line 3rd line and the following lines: Reason for changes
One of the most valuable features of Git is the ability to undo mistakes. When you make a new commit, Git stores a snapshot of your project so that you can go back to an earlier version when you need to.
There are two ways to undo changes: git revert and git reset.
You can use the git revert command to safely undo a commit that has already been pushed.
While you can also delete a previous commit from the history using git reset or git rebase -i, it is generally not a good idea because it causes the remote repository to become desynchronized with the local repositories of other members.
You can discard commits that you no longer need using the git reset command. You can specify the scope for the reset command by going into reset mode.
There are three primary reset modes:
- Mixed (default)
Mixed mode restores the state of a changed index. Soft mode undoes a previous commit. Hard mode removes all traces of a commit. Below is a breakdown of each reset mode.
Remote repositories allow us to share our changes with other members of the team. They can be on a private server, on a different computer than yours, or hosted using a service like Backlog. Wherever yours is hosted, you’ll need to be able to sync your local repository with the remote repository frequently. You’ll do this using three commands: git push, git pull, and git merge.
In order to start sharing changes with others, you have to push them to a remote repository using the “push” command. This will cause the remote repository to update and synchronize with your local repository.
Whenever somebody pushes their changes to the shared remote repository, your local repository becomes out of date. To re-synchronize your local repository with the newly updated remote repository, simply run the git pull operation.
When the pull is executed, the latest revision history will download from the remote repository and import to your local repository.
Your push to the remote repository will be rejected if your local repository is out of date, possibly because there are some updates on the remote repository that you do not have locally yet.
If that is the case, you’ll have to use the git merge command to grab the latest change from the remote repository before you are allowed to push. Git enforces this to ensure that changes made by other members get retained in the history.
During a “merge”, Git will attempt to automatically apply those history changes and merge them with the current branch. However, if there is a conflict in changes, Git will throw an error prompting you to resolve the conflict manually.
Resolve merge conflicts
When merging two branches, you may come across a conflict that needs resolving before you can properly complete the merge. For example, when two or more members make changes on the same part of a file in the two different branches (remote and local branches in this case), Git will not be able to automatically merge them.
When this happens, Git will add some standard conflict-resolution markers to the conflicting file. The markers help you figure out which sections of the file need to be manually resolved.
In our example, everything above “=====” is your local content, and everything below it comes from the remote branch.
You must resolve the conflicting parts as shown below before you can proceed with creating a merge commit.
There are times when you need to revise your local commit history. This can include anything from changing your commit message to changing the order of your commits to squashing commits together. In this section, we’ll discuss how to rewrite history before sharing your work with others.
Git commit –amend
You can modify the most recent commit in the same branch by running git commit –amend. This command is convenient for adding new or updated files to the previous commit. It is also a simple way to edit or add comments to the previous commit.
Rebasing is the process of taking all the changes that were committed on one branch and applying them to a new branch.
Run git rebase and add in the -i option to rewrite, replace, delete, and merge individual commits in the history. You can also:
- Rewrite a past commit message
- Squash a group of commits together
- Add files that have not been committed
Git cherry pick
You can apply an existing commit from another branch to the current branch within the repository by using the git cherry-pick command. Cherry-picking allows you to:
- Move a commit that was committed to the wrong branch to the right branch.
- Add a commit to the current branch based on an existing commit from another branch.
Git merge –squash
Squashing is the process of merging multiple commits into a single commit.
If you run git merge and the –squash option, a new commit will group all of the commits from that branch together. The commit will be used to merge into the current branch.