Git is an extremely good distributed version control system. The system can record every change to a user’s files and also has powerful team collaboration capabilities: everyone can commit changes to the text without worrying about overwriting the operations of others. Github is furthermore a software source code hosting service version-controlled with Git. As of 2015, Github had more than nine million registered users and 21.1 million repositories. Github has become the largest code hosting website and open source community in the world.
GIT usage tutorial
Creating a repository
Choose a suitable place and create an empty directory
mkdir <dir-name>
cd <dir-name> #operate inside the repository
pwd #you can check the current directory
git init #turn the directory into a repository Git can manage, that is, initialize the repository
Afterwards a .git directory is created in the current directory; this directory is used by Git to track and manage the repository. A non-empty directory can also be used to create a Git repository
Writing and saving files
Write the file and place it in the <dir-name> directory (or a subdirectory)
Edit and save the file in plain text, saving the file encoding in UTF-8 format
git add <filename1> <filename2> ... #tell Git to add the files to the repository
git commit -m "..." #commit the files to the repository; enter the description of this commit after -m; multiple files can be committed at once
git status #check the current status of the repository, telling the user whether any file has been modified
git diff #check what exactly was modified in the files, or compare files
git log #show the commit log from most recent to oldest (the parameter --pretty=oneline can be added to change the display view)
git reset --hard HEAD^ #revert the files to the previous version
In Git, HEAD represents the current version, the previous version is HEAD^, the one before that is HEAD^^, and N versions back can be written as HEAD~N
git reset --hard <fileID> #jump the file version to the file with version ID <fileID>
git reflog #records every operation of the user, from which you can check the version number before the file was reverted
Working directory and staging area
Working directory
The directory you can see on the computer is the working directory, used to store files
Repository and staging area
There is a hidden directory .git under the working directory; this is the git repository, and the repository contains the staging area (stage/index)
Roughly how Git works
Adding files to the Git repository takes two steps:
git addadds the file into the staging area, that is, adds the modification or related operations on the file to the staging areagit commitcommits the changes, that is, submits everything in the staging area to the current branch
Undoing changes to files
git checkout -- <filename> undoes all modifications to -- in the command is very important, without -- it becomes the command for switching to another branch
Cases of undoing changes to files
As for when changes to a file need to be undone, there are roughly two cases:
- If
<filename>has been modified but not yet put into the staging area, then after the command executes the changes are undone and the file returns to exactly the same state as the repository - If
<filename>has already been added to the staging area and then modified again, then after the command executes the changes are undone and the file returns to the state it had after being added to the staging area In short, it makes the file return to the state of the most recentgit commitorgit add
Summary of undoing and reverting
- When you have messed up the content of a file in the working directory and want to simply discard the modifications in the working directory, use the command
git checkout -- <filename> - When you have not only messed up the content of a file in the working directory but also added it to the staging area, and want to discard the modifications, do it in two steps: use the command
git reset HEAD <filename>to go back to case 1, then continue with the operation in 1 - When you have already committed an inappropriate modification to the repository and want to undo this commit, refer to version reverting — provided it has not been pushed to the remote repository
Version reverting: git reset --hard <ID> jumps the file to the version with version number ID; HEAD represents the latest file version
Undoing deletions in Git
Deletion is also a modification operation in Git
Normally, after committing to the repository, we delete a file directly in the file manager (or with the rm command); git status will tell you which files have been deleted, and there are then two choices:
- If you really want to delete it from the repository, run the
git rmcommand to delete it and thengit commit - If you deleted it by mistake, you can run
git checkout -- <filename>to restore the mistakenly deleted file to the latest version
git checkoutin fact replaces the version in the working directory with the version in the repository; whether the working directory version was modified or deleted, it can be “restored with one click”, The commandgit rmis used to delete a file. If a file has already been committed to the repository, you never need to worry about deleting it by mistake, but you can only restore the file to the latest version, and you will lose the content after the most recent modification commit
Creating an SSH Key
ssh-keygen -t rsa -C "youremail@example.com"
After creating it, you can find the .ssh directory in the user’s home directory, containing the two files id_rsa and id_rsa.pub; these two files are the key pair of the SSH Key. id——rsa is the private key and must not be leaked, while id_rsa.pub is the
public key and can be published. Then log into Github to configure it: go to the “SSH Key” page, click “Add SSH Key”, fill in any title and paste the content of the id_rsa.pub file into the Key text box
Github allows adding multiple Keys
Associating a remote repository
First create a new repository on Github (or use an existing one), then run the following command in a local repository:
git remote add origin git@github.com:<accountname>/<localreponame>.git
After adding it, the default name of the remote repository in Git is origin; it can be changed:
git push -u origin master
The git push command actually pushes the current branch master to the remote,
If this is the first time you push the master branch you need to add the -u parameter; Git will not only push the content of the local master branch to the new remote master branch, but also associate the local master branch with the remote master branch,
which simplifies the command for later pushes or pulls. Afterwards, as long as you have made a local commit, you can complete the submission with the command: git push origin master
When using Git’s clone or push command for the first time you will get an SSH warning; just type yes
#associate a remote repository
git remote add origin git@server-name:path/repo-anme.git
Cloning a remote repository to local
After creating a repository in Github, you can use git clone to clone a local repository
git clone git@github.com:<git repository address>
Git supports multiple protocols, including https
windows systems: git clone <URL of the Git remote repository>
Git branches
git branch #view branches
git branch <name> #create a branch
git checkout <name> #switch branches
git checkout -b <name> #create + switch branch
git merge <name> #merge some branch into the current branch
git branch -d <name> #delete a branch
Multiple branches share the staging area, that is, if you only add without committing on branch 1, the staging area has in fact already recorded that modification, and even switching to branch 2 afterwards and committing there is a valid operation
When Git cannot merge branches automatically, the conflict has to be resolved first. Commit after resolving the conflict,
with the git log --graph command you can see the branch merge graph, and git status can also show the conflicting files
e.g: git log --graph --pretty=oneline --abbrev-commit
Git branch management
When merging branches, adding the --no-ff parameter allows merging in normal mode; the history after such a merge has branches, so you can tell that a merge was once done, whereas with fast-forward merging you cannot tell that a merge was done
git merge --no-ff -m"..." <name>
Merging a branch in normal mode (that is, disabling fast forward) requires creating a new commit for this merge, so add the -m parameter and write the commit description
Branch strategy:
- In actual development we should manage branches according to a few basic principles:
- The master branch should be very stable, that is, used only to release new versions, and you do not normally work on it;
- Work happens on the dev branch, that is, the devd branch is unstable, and at some point the dev branch is merged into the master branch;
- Everyone works on the dev branch, and each person has their own branch; when it needs to be saved, just merge it into the dev branch
Bug branches
The git stash command is equivalent to taking a snapshot of the current working environment, so that you can restore the environment later and continue working
Fix the bug on whichever branch it should be fixed on, and create a temporary branch from that branch
Commit and delete the branch after fixing
git stash list #check whether a stash exists
git stash apply #restore the stash content; this command does not delete the stash content after running
git stash drop #delete the stash content
git stash pop #restore the stash content and delete it at the same time
When fixing a bug while the work at hand is not finished, first git stash the work in progress, then go and fix the bug, and after fixing it git stash pop back to the work in progress
Feature branches (adding new features)
When developing a new feature it is best to create a new branch,
To discard a branch that has never been merged, you can force its deletion with git branch -D <name>
Collaboration
git remote shows information about the remote repositories
git remote -v shows detailed information about the remote repositories (it displays the addresses of the
- Pushing branches:
Pushing a branch means pushing all the local commits on that branch to the remote repository. When pushing, the local branch must be specified
git push <remote repository name> <local repository name>
git pull #fetch the latest commits from the remote repository
Merge locally after fetching and push again after resolving conflicts
- Working pattern:
- First, you can try to push your changes with
git push origin branch-name - If the push fails, it is because the remote branch is newer than your local version, so you need to try to merge first with
git push - If the merge has conflicts, resolve them and commit locally
- Once there are no conflicts or the conflicts have been resolved, pushing again with
git push origin branch-namewill succeed
If git pull says “no tracking information”, it means the link between the local branch and the remote branch has not been created; use the command git branch --set-upstream branch-name origin/branch-name (this command establishes the association between the local branch and the remote branch)
Tag management
When releasing a version, we usually first tag the repository, so that the version at the time of tagging is uniquely determined. At some point in the future, taking a certain version of a certain tag means taking out the version corresponding to the moment the tag was created. A tag is also a snapshot of the repository
Although a Git tag is a snapshot of the repository, it is in fact a pointer to a certain commit (branches can move, tags cannot)
A tag is just an easy-to-remember name bound to a certain commit
git tag <name> #to tag in git you should first switch to the branch that needs the tag
git tag #view all tags; by default a tag is created on the commit of the latest submission
git tag <name> <commit ID> #tag the commit with the corresponding ID
Tags are not listed in chronological order but sorted alphabetically; git show <tagname> can be used to view tag information
git tag -a <tagname> -m "..." #create a tag with a description; -a specifies the tag name and -m specifies the description text
git tag -d <tagname> #delete a local tag, because created tags are only stored locally and are not automatically pushed to the remote
git push <remote repository name> <tagname> #push a certain tag to the remote
git push <remote repository name> --tags #push all local tags not yet pushed to the remote in one go
If in the first line of code above the parameter -s is used instead of -a, a PGP-signed tag can be created
Deleting a tag that has already been pushed to the remote:
git push <remote repository name> :refs/tags/<tagname>
On Github you can freely Fork open source repositories;
you have read and write permission on the repository you Forked;
you can push Pull requests to other people’s repositories to contribute code;
after Forking someone else’s repository, clone the repository under your own account, so that you can push your modifications
Customizing Git
git config --global color.ui true #git will display different colors appropriately
- Ignoring files
In the root directory of the Git working directory there is a .gitignore file (create it if it does not exist); fill in the names of the files to be ignored, and Git will automatically ignore these files
Principles for ignoring files:
- Ignore files automatically generated by the operating system, such as thumbnails;
- Ignore intermediate files and executable files generated by compilation — that is, files automatically generated from other files do not need to be put into the repository;
- Ignore your own configuration files containing sensitive information, such as configuration files that store passwords
Afterwards commit .gitignore to Git as well, and the ignored-file configuration is complete
git check-ignore #check the .gitignore file
git add -f <filename> #force adding a file
We can also version-manage .gitignore
- Setting aliases
git config --global alias <alias> <original command name>
The –global parameter is a global parameter, meaning these commands are effective in all Git repositories on the computer
When configuring Git, adding --global applies to the current user; without it, it only applies to the current repository.
Each repository’s Git configuration file is stored in the .git/config file,
with aliases after [alias]; to delete an alias just delete the corresponding line.
The current user’s Git configuration file is the hidden file .gitconfig in the user’s home directory
Setting up a Git server (linux ubuntu or debian)
- Install git:
sudo apt-get install git; - Create a git user to run the git service:
sudo adduser git; - Set up certificate login: collect the public keys of all users who need to log in, that is, their id_rs.pub files, and import all public keys into the /home/git/.shh/authorized_keys file (the name can be changed);
- Initialize the Git repository:
sudo git init --bare <reponame>; the parameter –bare creates a bare repository, that is, one without a working directory (Git repositories on a server usually end with .git; after creating it change the owner to git withsudo chown -R git:git <reponame>); - Disable shell login: for security reasons, the git user created in step 2 is not allowed to log into the shell; this can be done by editing the /etc/passwd file
Find a line like:
git:x:1001:1001:,,,:/home/git:/bin/bashand change it to:git:x:1001:1001:,,,:/home/git:/usr/bin/got-shellso that when the user logs in with a shell they are automatically logged out; - Clone the remote repository:
git clone git@server:/srv/<reponame>; run it on each person’s own computer
Reference:
Liao Xuefeng’s Git tutorial