Git Essentials by Ferdinando Santacroce

The main difference between Version Control Systems (VCS) and Distributed Version Control Systems (DVCS)  is the  constraint—in the centralized system —to have a remote server from which to get and in which to put your files; needless to say, if the network is down, you are in trouble. In DVCS, on the other hand, you can either have or not have a remote server (even more than one), but you can work offline, too. All your modifications are locally recorded so that you can sync them at some other time.

 

Type git (or the equivalent, git --help), result in a short help page, with a list of common commands.

 

In Git, every modification you make in a repository has to be signed with the name and email of the author. So, before

doing anything else, we have to tell Git this information.

git config --global user.name "Mike"

git config --global user.email "[email protected]"

A repository is a container for your entire project; every file or subfolder within it belongs to that repository, in a consistent manner. Physically, a repository is nothing other than a folder that contains a special .git folder, the folder where the magic happens. 

echo "Git rocks!" >> file.txt /*create a file*/

cat file.txt /*check the content of the file*/

git add file.txt /*put file file.txt under the control of git*/

git status /*check the status of the repository*/

git commit --message "First commit" /*--message 是subcommand, 也可以用-m代替;*/

dir -all/*list all files in the folder, including hidden files and folders.*/

The abort key combination 'Ctrl + C'.


echo "My shopping list repository" > README.md /*create a file.*/

git add . /*add all the new or modified files in one shot */

git config user.name "Ferdinando Santacroce"

git config user.email [email protected]

git commit --amend --reset-author /* all the commits done in this repository will be signed by "Ferdinando Santacroce", with the [email protected] email */

git log /*verify the commit just created*/

git log --format=fuller

git log --format=raw  /*tree*/

等同于

git cat-file -p 17c2b /* 17c2b are the initial letters of the hash of the commit; -p 代表pretty-print;*/

There are different commands and options that end up doing the same thing; this is a common feature of Git, and it's due to its organic growth across the years. Git changed (and changes) continuously, so the developers have to guarantee some backward compatibility when introducing new commands


Linus divides the Git commands into two families, the highest-level ones, comfortable for a user interested in the most common operations (porcelain) and those used internally by the same (but usable at the discretion of the more experienced users) to perform lower-level operations (plumbing).


Git uses four different types of objects, and commit is one of these. Then there are tree, blob, and annotated tag.


Blobs are binary files, nothing more and nothing less. These byte sequences, which cannot be interpreted with the naked eye, retain inside information belonging to any file, whether binary or textual, images, source code, archives, and so on. Everything is compressed and transformed into a blob before archiving it into a Git repository. As already mentioned previously, each file is marked with a hash; this hash uniquely identifies the file within our repository, and it is thanks to this ID that Git can then retrieve it when needed, and detect any changes when the same file is altered (files with different content will have different hashes).


echo "banana" | git hash-object --stdin

/* The git hash-object command is the plumbing command to calculate the hash of any object; in this example, we used the --stdin option to pass as a command argument the result of the preceding command, echo "banana"; in a few words, we calculated the hash of the string "banana" ; an object, whatever it is, will always have the same hash in any repository, in any computer, on the face of the Earth.

Git calculates the hash on the content of the file, not in the file itself; if you have two different files with the same content, even if they have different names and paths, in Git you will end up having only one blob.  */


ll .git/ /*list all content within the folder .git*/

 

ll .git/objects/ /*list content within the folder objects within folder .git*/


When a file is untouched, while committing Git creates a tree where the blob for the file points to the already existing one, recycling it and avoiding waste of disk space.

The same applies to the trees: if my working directory has some folders and files within them that will remain untouched, when we do a new commit Git recycles the same trees.


git commit -am "Add an orange" /* add to this commit all the modified files that I have already committed at least one time before and commit them; this is used to skip "git add" */


Branches are nothing but labels that are on the tip commit, the last one. This commit, our leaf, must always be identified by a label so that its ancestors commits can be reached while browsing within a repository.

 

git branch berries /*create a branch called berries*/

 

git checkout berries /*switch to branch 'berries'*/

 

HEAD is a reference. It represents a pointer to the place on where we are right now, nothing more, nothing less. In practice

instead, it is just another plain text file.

 

When you switch a branch, Git goes to the commit the branch is pointing to, and following the parent relationship and analyzing trees and blobs, rebuilds the content on the working directory accordingly, getting hold of that files and folders (that is the same Subversion can do with the switch branch feature, actually).

 

git log --oneline --graph --decorate --all /*see all branches.*/

 

git checkout - /*move to the branch one was before switching*/

 

git reset --hard master /* The git reset actually moves a branch from the current position to a new one; here we said Git to move the current berries branch to where master is, and the result is that now we have all the two branches pointing to the same commit. */


Any Git command, followed by the --help option, will open for you the internal man page for it.


git reset --hard HEAD^ /*one step back*/

 

git checkout HEAD^  /*enter detached HEAD state; in this state,HEAD does not reference a branch, but directly a commit,*/

 

git branch bug 8999b /*create a branch that points to a commit*/


git reflog show

 

git tag bugTag /*tags are lables pin to a commit; Even tags are references, and they are stored, as branches, as simple text files in the tags subfolder within the .git folder */

 

git tag myTag 07b1858 /* create a tag that points a specified commit */

 

git tag -d /*remove a tag*/

 

git tag -a annotatedTag 8999b /*add an annotated tag.*/


The effect of git commit is to create a new commit with the content of the staging area, and then empty it.

 

git diff /*compare working tree and staging area*/

 

git diff --cached HEAD  或者 git diff --cached /* see the differences between the last committed version of the shoppingList.txt file and the one added into the staging area */

 

The staging area, also known as an index, sometimes is called cache.

 

git diff HEAD /* compare the HEAD version with the working tree one.*/


In Git, we work at three different levels:

The working tree (or working directory)

The staging area (or index, or cache)

The HEAD commit (or the last commit or tip commit on the current branch)

 

When we modify a file, we are doing it at working tree level; when we do a git add, we are actually copying the changes from the working tree to the staging area. At the end, when we do a git commit, we finally move the changes from the staging area to a brand new commit, referenced by HEAD, which will become part of our repository history

 

git reset HEAD shoppingList.txt /* unstage a modification to a file */

 

git checkout -- shoppingList.txt /*remove modification did to file shoppingList.txt*/

 

git checkout is for switching branches and git checkout -- is for discarding local changes.

git reset -- is actually the same as doing a git reset HEAD

 

To be true, the double-dash -- notation is not mandatory; if you do a git checkout  or git reset without --, in 99% of cases Git does what you expect. The double-dash is needed when, due to a coincidence, there is a file and a branch with the same name: in that case, Git has to know if you want to deal with branches, for example switching to another one with git checkout, or if you want to manage files.

In this situation, the double-dash is the way to tell Git I want to handle files, not branches.

 

git reset --hard master /* discard all the latest changes and go back to the latest commit on master, cleaning up even the staging area*/

 

git branch -d bug /*delete branch bug*/

 

echo -n "gr" >>shoppingList.txt /*add characters, but not new line, to the file.*/


Basically, a Git remote is another "place" that has the same repository you have on your computer.

 

git clone /d/grocery /*把D盘grocery文件夹 克隆岛当前文件夹*/

 

git clone https://github.com/Li-YangZhong/Cookbook.git /*clone a remote repository to a local folder.*/

 

git push /* upload local work to a configured remote location */

 

With the git push -u origin Risotti command, we told Git to upload our Risotti branch (and the commits within it) to the origin; with the -u option, we set the local branches to track the remote one.

 

If you want to see remotes actually configured in your repository, you can type a simple git remote command, followed by -v (--verbose) to get some more details


mkdir HelloWorld /*create a folder*/

 

echo "Hello World!" >> README.md /*Create a file named README.md with content "Hellow World!" in it.*/

 

To publish our HelloWorld repository, we simply have to add its first remote; adding a remote is quite simple: git remote add origin

 

The upstream remote is not present, you have to add it manually; to add it, use the git remote add command:

git remote add upstream https://github.com/Li-YangZhong/Spoon-Knife.git

 

To create a pull request, you have to go on your GitHub account and make it directly from your forked account; but first, you have to know that pull requests can be made only from separated branches.

 

Configuration options are stored in plain text files. The git config command is just a convenient tool to edit these files without the hassle of remembering where they are stored and opening them in a text editor.

To get a list of all the configurations currently in use, you can run the git config -- list command; if you are inside a repository, it will show all the configurations, from repository to system level. To filter the list, append optionally --system, --global or -- local options to obtain only the desired level configurations.

 

git reset HEAD -- myFile.txt /*remove file myFile.txt from the staging area.*/

 

git log -1 HEAD /* read about your last commit */

 

git diff --cached HEAD^ /*see a diff against your last commit.*/

 

alias gti='git' /*create a Bash shell alias*/

 

git archive master --format=zip --output=../repoBackup.zip /*backup master branch*/

 

git archive HEAD --format=zip --output=../headBackup.zip /*archiving only the last commit*/


git bundle create ../repo.bundle master /* export a snapshot from your repository *

git clone ../../repo.bundle repo -b master /*restore a bundle*/


Rules of writing commit messages:

  • Making only one change per commit.
  • Describing in the commit the change, not what have you done.
  • Start with capital letters, and do not end sentences with periods - they are useless, and even dangerous.

Different workflow types:

https://nvie.com/posts/a-successful-git-branching-model/

http://scottchacon.com/2011/08/31/github-flow.html

https://trunkbaseddevelopment.com/


TortoiseSVN (http://tortoisesvn.net)  is a Subversion client.

https://www.sourcetreeapp.com/ a free Git GUI tool.

https://learngitbranching.js.org/ a web app for learning git

Visualizing Git Concepts with D3 can help you grasp all the most important commands visually. Find it at https://onlywei.github.io/explain-git-with-d3/

https://www.gitminutes.com/

你可能感兴趣的:(技术类书籍笔记,Git)