During project development, version control tools such as svn and Git are always used. As Git has developed, it has gradually been adopted by more and more people, and is even slowly replacing svn. Below we will introduce how to use Git from the aspects of creating a Git repository, common basic Git commands, Git branch management, viewing Git commit history, Git tags, and Git remote repositories. Of course, all the commands involved below are run in Git bash, so you must install Git first. As for how to install Git, we won’t cover that here—there are plenty of installation tutorials online.

Creating a Git Repository

There are several ways to create a git repository:

  • git init: initialize a git repository
  • git clone: clone a git repository

The following describes these methods in detail:

1. git init

Git uses the git init command to initialize a Git repository. After running git init, a .git directory is generated. This directory contains the resource data and is only generated in the root directory of the repository.

If you want to use the current directory as a Git repository, you only need to run the following command:

git init

The result is as follows:

After running this command, an .init folder is generated in the current directory, and a master branch is generated by default.

If you want to generate the repository in a specified directory, the command is as follows:

git init newDir

newDir is the path of the repository. After execution, a .git directory is generated under the newDir directory. The specific result is as follows:

After running this command, a newtest folder is generated in the current directory, and an .init folder is generated inside that folder.

2. git clone

You can use the git clone command to copy a project from a Git repository, similar to svn checkout in SVN. The command format is:

git clone <url> [directory]

url is the address of the git repository, and directory is the local directory. For example, to clone a certain Git code repository, you can use the following command:

git clone git://github.com/schacon/grit.git

After execution, the repository is generated in the current directory. If you want to generate it in a specified directory, you can append a specific path, for example:

git clone git://github.com/schacon/grit.git newgit

The following is the result of cloning a repository:

When using git clone, you can use different protocols, including ssh, git, https, etc. Among them, ssh is the most commonly used because it is faster and can be configured with a public key to avoid entering a password. The various formats are as follows:

git clone [email protected]/schacon/grit.git         --SSH协议
git clone git://github.com/schacon/grit.git          --GIT协议
git clone https://github.com/schacon/grit.git      --HTTPS协议

Using Basic Git Commands

The following introduces several commonly used commands in git:

  • git config: configuration information
  • git add: add files to the cache
  • git status: view file status
  • git diff: view detailed update information
  • git commit: commit
  • git reset HEAD: unstage
  • git rm: delete
  • git mv: move or rename

The following describes these commands in detail:

1. git config

We can use git config to configure the username and email address, making it easier to commit code to a remote repository. The specific format is as follows:

git config --global user.name '你的用户名'
git config --global user.email '你的邮箱'

2. git add

The git add command can add files to the cache. For example, in a new project, it is very common to add all files, and you can use the following command:

git add .

Of course, we can also specify a certain type of file. For example, to add java files to the cache, you can use the following command:

it add *.java

For example, we can create two files and add them to the cache. The specific operations are as follows:

3. git status

We can use the git status command to view the status of related files. Simply run the following command:

git status

If there are modified files, the result is as follows:

According to the prompts from the git status command above, we can get three ways to handle the situation:

  • Command to stage files: git add

  • Command to discard modifications to unstaged files: git checkout –

  • Command to stage and commit modified files: git commit -a

If you are fairly familiar with the various states of Git, you can also use git status -s to view abbreviated status. This abbreviated status is similar to that in SVN: M - modified, A - added, D - deleted, R - renamed, ?? - untracked, etc. If there are modified files, the result is as follows:

4. git diff

Run git diff to view detailed update information. Unlike git status, which only shows update status, git diff can show the specific detailed differences between changes written to the cache and modifications that have been made but not yet written to the cache.

  • Changes not yet cached: git diff
  • View cached changes: git diff --cached
  • View all cached and uncached changes: git diff HEAD
  • Show a summary instead of the entire diff: git diff --stat

For example, we modify the contents of the test.txt file and use git diff to view the detailed modification information:

After that, we add the modifications to the cache and use git diff again to view the detailed modification information:

5. git commit

git commit adds the contents of the cache area to the repository. You can append the -m option to provide a commit comment on the command line. The format is as follows:

git commit -m "第一次版本提交"

If you feel that you have to run add before every commit and want to skip the add step, you can use the -a option directly, for example:

git commit -am "第一次版本提交"

For example, we can create a file, add it to the cache, and then commit it. The specific operations are as follows:

6. git reset HEAD

The git reset HEAD command is used to unstage cached content. For example, if we want to unstage the committed test.txt file, we can use it as follows:

git reset HEAD test.txt

After execution, when you use commit again, the test.txt file will not be committed.
For example, we first modify the test1.txt and test2.txt files, then add both to the cache, then use the git reset HEAD command to restore test1.txt, and finally commit. The specific operations are as follows:

As you can see, the modified test1 file was not committed after git reset HEAD. In short, run git reset HEAD to cancel a previous git add.

7. git rm

(This is part 1 of 3 of the same post.)

If you simply delete a file manually from the working directory, running git status will show it under “Changes not staged for commit”. To remove a file from Git, you must remove it from the tracked file list and then commit. You can do it as follows:

git rm <file>

If the file was modified before deletion and has already been placed in the staging area, you must use the force delete option -f.

git rm -f <file>

If you want to remove the file from the staging area but still keep it in the current working directory—in other words, remove it only from the tracked list—use the --cached option.

git rm --cached <file>

You can delete recursively: if a directory is passed as the argument, all subdirectories and files in that directory will be recursively deleted:

git rm –r *

For example, let’s remove the hello.java file created above:

8. git mv

The git mv command is used to move or rename a file, directory, or symbolic link. For example, to rename a test.txt file to newtest.txt, you can use the following command:

git mv test.txt newtest.txt

For example, let’s rename the test1.txt file above to test.txt:

Git Branch Management

Almost every version control system supports branch management. Using branches, we can separate from the mainline and continue development without affecting it. Below is an introduction to the commonly used branch commands in Git:

  • git branch: Command to list branches
  • git branch (branchname): Command to create a branch
  • git checkout (branchname): Command to switch branches
  • git merge: Command to merge branches
  • git branch -d (branchname): Command to delete a branch

The following sections describe these commands in detail:

1. git branch

git branch can both list branches and create branches. With no arguments, git branch lists your local branches; with an argument, git branch creates a branch with that name.

To list branches, the command format is as follows:

git branch

The effect when executed in bash is shown in the following figure:

When we want to create a branch, we can add an argument after it. The command format is as follows:

git branch  branchname

For example, if we want to create a branch named test, we can do the following:

Now we can see that there is a new branch, test. As for the master branch, when we run git init, Git creates the master branch for you by default.

2. git checkout (branchname)

git checkout can switch branches. The command format is as follows:

git checkout branchname

If we want to switch to the test branch just created above, we can do the following:

As you can see, before execution, the current branch is master; after execution, the current branch is test. At this point, you can continue working in the switched branch without affecting other branches.

We can also use the git checkout -b (branchname) command to create a new branch and immediately switch to it, so that we can work in that branch. For example, if we want to create a newtest branch and switch to it after creating it, we can do the following:

As you can see, before execution we are still on the master branch; after execution, we go directly into the newtest branch.

3. git merge

The git merge command can merge any branch into the current branch. The command format is as follows:

git merge branchname

For example, we create a new newtest branch and add a test3.txt file in it. Then, on master, we merge the changes from the newtest branch into master. The result is as follows:

As you can see, test3.txt now also exists in master.

Merge Conflicts

When merging, the biggest challenge is conflicts. Merging is not just a simple operation of adding or removing files; Git also merges modifications. If we modify the same file in two branches at the same time and then merge, conflicts may arise. Conflicts are not scary; what matters is how to resolve them. Below is a small example demonstrating how to resolve a merge conflict.

Still using the repository above, there are now two branches: master and newtest. Both branches contain the test.txt file. At this point, we modify the file in both branches, then commit, and finally merge newtest into master. The specific steps are as follows:

  1. First modify the test.txt file in the master and newtest branches, and commit:

  1. Then merge the changes made in the newtest branch into the master branch:

As you can see, the changes made in the newtest branch conflict with those made in the master branch. Resolve this according to the specific situation. As shown below, we keep the content from both branches, then run add and commit:

At this point, a simple merge is complete. In actual project development, merges are much more complex than this, and you need to operate according to the specific situation.

4. git branch -d (branchname)

git branch -d can delete a branch. The command format for deleting a branch is as follows:

git branch -d (branchname)

For example, to delete the test branch:

Viewing Commit History in Git

After committing several updates with Git, or after cloning a project, you may want to review the commit history. We can use the git log command to view it. For example, to list the historical commit records, do the following:

Below are several options for viewing history:

  • –oneline: View a concise version of the history
  • –graph: View when branches and merges appeared in the history
  • –reverse: Display all logs in reverse
  • –author: Find commit logs by a specified user
  • –since, –before, --until, –after: Specify date filters
  • –no-merges: Option to hide merge commits

We can use the –oneline option to view a concise version of the history:

We can also use the –graph option to see when branches and merges appeared in the history:

This way, we can see more clearly when the work diverged and when it merged back together. We can also use the –reverse parameter to display all logs in reverse:

If you only want to find commit logs by a specified user, you can use the command: git log --author. For example, suppose we want to find the commits by qtqt in the Git source code:

If you want to specify dates, you can use several options: –since and --before, but you can also use --until and --after. The –no-merges option hides merge commits.

For example, if I want to see all commits in the Git project before August 1 and after July 29, I can run this:

In many cases, it is useful to know which branch or tag each commit is associated with. The –decorate flag makes git log show all the references (such as branches and tags) that point to each commit, like this:

Git Tags

Tags make it easy to permanently remember a particular commit snapshot. For example, when we release a new version, we can give it a “vx.x” version number by tagging it with git tag.

Creating a new tag

You can create a tag with git tag -a vx.x. The -a option means “create an annotated tag”. You can also run it without -a, but then Git will not record when or by whom the tag was created, and it will not let you add a tag annotation.
For example, let’s create a tag for the example above:

Appending a tag

If we forget to tag a commit and have already published it, we can append a tag afterwards. For example, suppose we released commit d6f7147 but forgot to tag it at the time. We can still do it now:

Viewing tags

If we want to view all tags, we can use the following command:

git tag

The result looks like this:

Command for specifying tag information:

git tag -a <tagname> -m "某某标签"

Command for a PGP-signed tag:

git tag -s <tagname> -m "某某标签"

Git Remote Repositories

The Git commands we have used so far all run locally. If you want to share your code through Git or collaborate with other developers, you need to put the data on a server that other developers can connect to. This section uses GitHub as the remote repository to introduce how to use Git remote repositories.

Here are several commonly used remote repository commands:

  • git remote add: add a remote repository
  • git remote: view the current remote repositories
  • git fetch, git pull: fetch from a remote repository
  • git push: push to a remote repository
  • git remote rm: delete a remote repository

1. git remote add

git remote add adds a remote repository. Its command format is as follows:

git remote add [alias] [url]

The [alias] parameter is the alias, and [url] is the address of the remote repository. For example, we can add the https://github.com/qtqt/test.git repository locally and name it test, as follows:

2. git remote

git remote shows the current remote repositories. The result looks like this:

As you can see, it includes the repository with the alias test added above.

3. git fetch, git pull

git fetch can fetch data from a remote repository. If there are multiple remote repositories, we can append the repository alias, as follows:

After this command finishes, you need to run git merge to merge the remote branch into your current branch. Suppose you have configured a remote repository and want to fetch updated data. You can first run git fetch [alias] to tell Git to fetch data that it has and you do not, and then run git merge [alias]/[branch] to merge any updates on the server (assuming someone has pushed to the server at this point) into your current branch. The operation is as follows:

After it finishes, you can find the remote repository’s files in your local repository. This approach only works if the local repository is empty; if it is not empty, you will get the error: fatal: refusing to merge unrelated histories.

The git pull command fetches from another repository or local branch and integrates it. In the default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD. Its usage is:

git pull [options] [<repository> [<refspec>…]]

For example, we can pull the remote repository locally. If the local repository and the remote repository are actually two independent repositories, the --allow-unrelated-history option resolves the issue.

The difference between git fetch and git pull:

  1. git fetch: essentially fetches the latest version from the remote to the local repository and does not merge automatically.
  2. git pull: essentially fetches the latest version from the remote and merges it into the local repository.

4. git push

git push pushes your new branch and data to a remote repository. Its format is as follows:

git push [alias] [branch]

For example, we can push the files committed earlier to the remote repository:

5. git remote rm

git remote rm deletes a remote repository. Its format is as follows:

git remote rm [别名]

For example, we can first add a repository named test2 and then delete it, as follows:

Alright, that basically covers the commonly used Git operations.