一、git 全局配置
全局配置:
bogon:~ yuanjicai$ git config --global user.name meteor
bogon:~ yuanjicai$ git config --global user.email [email protected]
bogon:~ yuanjicai$ git config --global color.ui true
查看配置:
bogon:~ yuanjicai$ git config --list | tail -3
user.name=meteor
[email protected]
color.ui=true
bogon:~ yuanjicai$
实质上是将配置写入了~/.gitconfig文件(当然直接修改该文件也可以达到配置的目的)
bogon:~ yuanjicai$ ls .gitconfig
.gitconfig
bogon:~ yuanjicai$ cat .gitconfig
[user]
name = meteor
email = [email protected]
[color]
ui = true
bogon:~ yuanjicai$
二、git新建项目及初始化
方法一、新建立一个项目目录:
bogon:~ yuanjicai$ mkdir -p github/project
bogon:~ yuanjicai$ cd github/project/
bogon:project yuanjicai$ git init初始化仓库
Initialized empty Git repository in /Users/yuanjicai/github/project/.git/
bogon:project yuanjicai$ ls -a
....git
bogon:project yuanjicai$ cd .git
bogon:.git yuanjicai$ ls
HEADconfighooksobjects
branchesdescriptioninforefs
bogon:.git yuanjicai$ git 保存分支的地方
方法二:
bogon:github yuanjicai$ pwd
/Users/yuanjicai/github
bogon:github yuanjicai$ ls
project
bogon:github yuanjicai$ git clone https://github.com/kennethreitz/requests.git
Cloning into ‘requests‘...
remote: Counting objects: 17906, done.
remote: Compressing objects: 100% (35/35), done.
remote: Total 17906 (delta 11), reused 0 (delta 0), pack-reused 17871
Receiving objects: 100% (17906/17906), 4.79 MiB | 643.00 KiB/s, done.
Resolving deltas: 100% (11665/11665), done.
Checking connectivity... done.
bogon:github yuanjicai$ ls
projectrequests
bogon:github yuanjicai$ ls requests/
AUTHORS.rstMakefilerequests
CONTRIBUTING.mdNOTICErequirements-to-freeze.txt
HISTORY.rstREADME.rstrequirements.txt
LICENSEdocssetup.py
MANIFEST.inexttests
bogon:github yuanjicai$ ls requests/.git
HEADconfighooksinfoobjectsrefs
branchesdescriptionindexlogspacked-refs
bogon:github yuanjicai$
三、建立文件并提交
bogon:github yuanjicai$ cd project/
bogon:project yuanjicai$ ls .git/
COMMIT_EDITMSGORIG_HEADconfighooksinfoobjects
HEADbranchesdescriptionindexlogsrefs
bogon:project yuanjicai$ ls
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ python test1.py
hello world
bogon:project yuanjicai$ vim test2.py
bogon:project yuanjicai$ python test2.py
hello YeeCall
bogon:project yuanjicai$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test1.py
test2.py
nothing added to commit but untracked files present (use "git add" to track)
bogon:project yuanjicai$ git add test1.py test2.py
bogon:project yuanjicai$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test1.py
new file: test2.py
bogon:project yuanjicai$ git commit -m "init commit"
[master 547a6b0] init commit
2 files changed, 2 insertions(+)
create mode 100644 test1.py
create mode 100644 test2.py
bogon:project yuanjicai$ git status
On branch master
nothing to commit, working tree clean
bogon:project yuanjicai$
四、git status
bogon:project yuanjicai$ vim test2.py
bogon:project yuanjicai$ python test2.py
hello YeeCall
hello git
bogon:project yuanjicai$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test2.py
no changes added to commit (use "git add" and/or "git commit -a")
bogon:project yuanjicai$ echo ‘*~‘ > .gitignore
bogon:project yuanjicai$ git add .gitignore
bogon:project yuanjicai$ git status -s
A .gitignore
M test2.py #第二位的M表示working directory有修改
bogon:project yuanjicai$ git add .gitignore
bogon:project yuanjicai$ git add test2.py
bogon:project yuanjicai$ git status -s
A .gitignore
M test2.py
bogon:project yuanjicai$ vim test2.py
bogon:project yuanjicai$ python test2.py
hello YeeCall
hello git
hello maven
bogon:project yuanjicai$ git status -s
A .gitignore
MM test2.py#第一个M表示staging有修改,第二个M表示working directory有修改
五、git diff
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ python test1.py
hello world
hello op
bogon:project yuanjicai$ git status -s
M test1.py
bogon:project yuanjicai$ git diff #默认git diff 只检查第二个标志位(即检查working directory与staging的数据是否一致)
diff --git a/test1.py b/test1.py
index a968078..6e43c62 100644
--- a/test1.py
+++ b/test1.py#表示本行为新添加的内容
@@ -1 +1,2 @@
print ‘hello world‘
+print ‘hello op‘
bogon:project yuanjicai$ git add test1.py
bogon:project yuanjicai$ git status -s
M test1.py
bogon:project yuanjicai$ git diff
bogon:project yuanjicai$ git diff --staged表示检查stage与history中的数据是否一致
diff --git a/test1.py b/test1.py
index a968078..6e43c62 100644
--- a/test1.py
+++ b/test1.py
@@ -1 +1,2 @@
print ‘hello world‘
+print ‘hello op‘
bogon:project yuanjicai$ git diff HEAD检查working directory与history是否一致,HEAD指针就指向最后一次提交的内容
diff --git a/test1.py b/test1.py
index a968078..6e43c62 100644
--- a/test1.py
+++ b/test1.py
@@ -1 +1,2 @@
print ‘hello world‘
+print ‘hello op‘
bogon:project yuanjicai$
bogon:project yuanjicai$ git diff --stat输出简要信息
bogon:project yuanjicai$ git diff --staged --stat
test1.py | 1 +
1 file changed, 1 insertion(+)
bogon:project yuanjicai$ git diff HEAD --stat
test1.py | 1 +
1 file changed, 1 insertion(+)
bogon:project yuanjicai$
bogon:project yuanjicai$ git commit -m ‘second commit‘从stage中将数据提交致history中
[master b89e642] second commit
1 file changed, 1 insertion(+)
bogon:project yuanjicai$
六、下载
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ cat test1.py
print ‘hello world‘
print ‘hello op.....‘
bogon:project yuanjicai$ git diff --stat
test1.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git add test1.py
bogon:project yuanjicai$ git diff --stat
bogon:project yuanjicai$ git diff --staged --stat 比较stage与history中的数据是否一致
test1.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git reset test1.py下载历史history中的最后一个版本致stage中
Unstaged changes after reset:
Mtest1.py
bogon:project yuanjicai$ git diff --staged --stat
bogon:project yuanjicai$ git diff HEAD --stat比较working directory与history中的数据是否一致
test1.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git checkout test1.py下载stage中的数据致working directory
bogon:project yuanjicai$ git diff HEAD --stat
bogon:project yuanjicai$ echo "xxxxx" >> test1.py
bogon:project yuanjicai$ git diff HEAD --stat发现stage与working directory已经不一致
test1.py | 1 +
1 file changed, 1 insertion(+)
bogon:project yuanjicai$ git checkout HEAD test1.py从history中直接下载历史版本到working directory
bogon:project yuanjicai$ git diff HEAD --stat
bogon:project yuanjicai$
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ cat test1.py
print ‘hello world‘
print ‘hello op !!‘
bogon:project yuanjicai$ git commit -am ‘third commit‘直接由working directory提交到history
[master bcc815a] third commit
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git diff --staged
七、删除数据
bogon:project yuanjicai$ echo "newfile" > test3.txt新建立文件test3.txt
bogon:project yuanjicai$ git add test3.txt添加并提交
bogon:project yuanjicai$ git commit -m "add test3.txt"
[master 5626d79] add test3.txt
1 file changed, 1 insertion(+)
create mode 100644 test3.txt
bogon:project yuanjicai$ git rm test3.txt删除test3.txt
rm ‘test3.txt‘
bogon:project yuanjicai$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: test3.txt
bogon:project yuanjicai$ git status -s
D test3.txt
bogon:project yuanjicai$ git commit -m "delete test3.txt"提交删除
[master 6e928e5] delete test3.txt
1 file changed, 1 deletion(-)
delete mode 100644 test3.txt
bogon:project yuanjicai$ git status -s
bogon:project yuanjicai$
bogon:project yuanjicai$
bogon:project yuanjicai$ git rm --cached test2.py仅删除staging中的文件
rm ‘test2.py‘
bogon:project yuanjicai$ git status -s
D test2.py
?? test2.py
bogon:project yuanjicai$ git reset test2.py再次从history中下载最后一个版本的文件
bogon:project yuanjicai$ git status -s
bogon:project yuanjicai$
bogon:project yuanjicai$ git rm --cache test2.py删除staging中的文件,将 working directory中的数据改名,并再次添加、提交
rm ‘test2.py‘
bogon:project yuanjicai$ mv test2.py test4.py
bogon:project yuanjicai$ git add test4.py
bogon:project yuanjicai$ git status -s
R test2.py -> test4.py
bogon:project yuanjicai$ git commit -m ‘rename test2.py to test4.py‘
[master 9845bda] rename test2.py to test4.py
1 file changed, 0 insertions(+), 0 deletions(-)
rename test2.py => test4.py (100%)
bogon:project yuanjicai$ git status -s
bogon:project yuanjicai$
八、stash暂存
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ cat test1.py修改源文件
print ‘hello world‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy‘
bogon:project yuanjicai$ git stash暂存当前正在进行的工作
Saved working directory and index state WIP on master: 9845bda rename test2.py to test4.py
HEAD is now at 9845bda rename test2.py to test4.py
bogon:project yuanjicai$ git status
On branch master
nothing to commit, working tree clean
bogon:project yuanjicai$ cat test1.py查看文件的内容(已经是之前没有修改前的内容)
print ‘hello world‘
print ‘hello op !!‘
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ cat test1.py编辑源代码文件(加了两个感叹号)
print ‘hello world!!‘
print ‘hello op !!‘
bogon:project yuanjicai$ git commit -am ‘quick update‘提交修改后的代码
[master 23a727c] quick update
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git stash list查看之前的暂存区
[email protected]{0}: WIP on master: 9845bda rename test2.py to test4.py
[email protected]{1}: filter-branch: rewrite
[email protected]{2}: WIP on master: 7f68a1a update
bogon:project yuanjicai$ git stash pop取出上次的暂存
Auto-merging test1.py
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test1.py
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/[email protected]{0} (33fb283741bb2747c55a9ddee45118f84b65c498)
bogon:project yuanjicai$ cat test1.py查看文件的内容(已经又回到了暂存时状态)
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy‘
bogon:project yuanjicai$
九、history 详解
git commit 之后就会提交到history area。然后history area 中存储 本次提交 的commit history 。每次的commit history 又由 parent 和 tree组成。而每个 parent 都会指向它前一个commit history 。最后一次提交的commit history被标记为 HEAD。前一次的被标记为 HEAD~ ,再前一次的被标记为HEAD~2 … 依次类推。
每个tree 又由多个文件或子目录组成,每个子目录下又可以由多个文件或子目录组成。
输入git log 可以看到之前提交的记录,以及每次提交时,每个commit history的hash码。
git cat-file -t HEAD 可以查看最后一次commit history 的指向类型
git cat-file -p HEAD 可以查看最后一次commit history中的内容,包括 tree 、parent的hash值
git cat-file -t Tree的hash 说明: -t 查看类型 -p 查看内容
git cat-file -p Tree的hash
可以查看到每个文件或目录也对应一个hash 值 。其中blob表示二进制
bogon:project yuanjicai$ git log --oneline
23a727c quick update
9845bda rename test2.py to test4.py
6e928e5 delete test3.txt
5626d79 add test3.txt
bcc815a third commit
b89e642 second commit
f492923 first commit
547a6b0 init commit
bogon:project yuanjicai$ git cat-file -t 23a727c
commit
bogon:project yuanjicai$ git cat-file -p 23a727c
tree bfbf9746b6279366e43117c3a94ff38692d1b60f
parent 9845bda97fdaca363b07f703a88259976a58261c
author meteor <[email protected]> 1471422986 +0800
committer meteor <[email protected]> 1471422986 +0800
quick update
bogon:project yuanjicai$ git cat-file -t HEAD 等同于git cat-file -t 23a727c命令
commit
bogon:project yuanjicai$ git cat-file -p HEAD 等同于 git cat-file -p 23a727c命令
tree bfbf9746b6279366e43117c3a94ff38692d1b60f
parent 9845bda97fdaca363b07f703a88259976a58261c
author meteor <[email protected]> 1471422986 +0800
committer meteor <[email protected]> 1471422986 +0800
quick update
bogon:project yuanjicai$ git cat-file -p HEAD~ 等同于 git cat-file -p 9845bda
tree bee185fc174697cf400998818e4ca099ca00e275
parent 6e928e51ab05ad2c60b0d51cfd6b7d0cae783ec3
author meteor <[email protected]> 1471422174 +0800
committer meteor <[email protected]> 1471422174 +0800
rename test2.py to test4.py
bogon:project yuanjicai$ git cat-file -p bee185f
100644 blob b25c15b81fae06e1c55946ac6270bfdb293870e8.gitignore
100644 blob b351508c3cadddc4ea579967d1c3177364fd5a48test1.py
100644 blob 5de2b690c836079832d879f9d2902ac58043f5b9test4.py
bogon:project yuanjicai$
bogon:project yuanjicai$ git cat-file -p b3515
print ‘hello world‘
print ‘hello op !!‘
bogon:project yuanjicai$ git show -p b3515
print ‘hello world‘
print ‘hello op !!‘
bogon:project yuanjicai$
十、tree-ish
bogon:project yuanjicai$ ls -A
.git.gitignoretest1.pytest4.py
bogon:project yuanjicai$ cd .git
bogon:.git yuanjicai$ ls
COMMIT_EDITMSGORIG_HEADconfighooksinfoobjects
HEADbranchesdescriptionindexlogsrefs
bogon:.git yuanjicai$ cat HEAD
ref: refs/heads/master说明 HEAD指向master分支
bogon:.git yuanjicai$ cd refs/
bogon:refs yuanjicai$ tree
.
|____heads
| |____mastermaster实质上是一个分支(branch)
|____original
| |____refs
| | |____heads
| | | |____master
| | |____stash
|____stash
|____tags
bogon:refs yuanjicai$ cat heads/master master又指向23a72
23a727c534d620339d3382d8284859f6a75f3194
bogon:refs yuanjicai$ git log --oneline | head -2hash23a727就是最后一次的提交
23a727c quick update
9845bda rename test2.py to test4.py
bogon:refs yuanjicai$ git cat-file -t 23a727 查看hash 23a727的类型是commit history
commit
bogon:refs yuanjicai$
#从上述可以看到 HEAD实质上是指几最后一个commit history的master branch ,而master branch再指向本次的commit history(另外 master~ 等同于 HEAD~)
bogon:refs yuanjicai$ git rev-parse HEAD
23a727c534d620339d3382d8284859f6a75f3194
bogon:refs yuanjicai$ git rev-parse master
23a727c534d620339d3382d8284859f6a75f3194
bogon:refs yuanjicai$
bogon:refs yuanjicai$ git rev-parse HEAD~说明:git rev-parse master~ 等同 git rev-parse HEAD~
9845bda97fdaca363b07f703a88259976a58261c
bogon:refs yuanjicai$ git rev-parse master~
9845bda97fdaca363b07f703a88259976a58261c
bogon:refs yuanjicai$
bogon:refs yuanjicai$ git rev-parse HEAD~^{tree}说明:查看倒数第二次commit history中的tree的hash值
bee185fc174697cf400998818e4ca099ca00e275
bogon:refs yuanjicai$ git rev-parse HEAD~:test1.py
b351508c3cadddc4ea579967d1c3177364fd5a48
bogon:refs yuanjicai$ git cat-file -p b3515
print ‘hello world‘
print ‘hello op !!‘
bogon:refs yuanjicai$ git show HEAD~:test1.py
print ‘hello world‘
print ‘hello op !!‘
bogon:refs yuanjicai$
十一、branch分支
bogon:project yuanjicai$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test1.py
no changes added to commit (use "git add" and/or "git commit -a")
bogon:project yuanjicai$ cat test1.py
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy‘
bogon:project yuanjicai$ git commit -am "stash commit"
[master 26415ad] stash commit
1 file changed, 2 insertions(+)
bogon:project yuanjicai$ git branch查看分支 (*表示当前的 branch)
* master
bogon:project yuanjicai$ git branch newidea创建分支
bogon:project yuanjicai$ git branch再次查看分支
* master
newidea
bogon:project yuanjicai$ git checkout newidea切换新的分支
Switched to branch ‘newidea‘
bogon:project yuanjicai$ cat .git/HEAD查看当前HEAD指向newidea分支
ref: refs/heads/newidea
bogon:project yuanjicai$ ls .git/refs/heads/查看现有分支的存储情况
masternewidea
bogon:project yuanjicai$ cat .git/refs/heads/*查看两个分支都指向同一个commit history
26415adb026d04fd2e375adedd6afcad8c0322ea
26415adb026d04fd2e375adedd6afcad8c0322ea
bogon:project yuanjicai$ git checkout master现次切换回master分支
Switched to branch ‘master‘
bogon:project yuanjicai$ git branch -d newidea删除指定分支
Deleted branch newidea (was 26415ad).
bogon:project yuanjicai$ git branch再次查看分支
* master
bogon:project yuanjicai$
bogon:project yuanjicai$ git checkout -b newcode参数-b 作用:检查如果没有branch则新建立
Switched to a new branch ‘newcode‘
bogon:project yuanjicai$ ls
test1.pytest4.py
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ cat test1.py
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy‘
print ‘zzzzzzzzzzz‘
bogon:project yuanjicai$ git commit -am ‘newcode update‘
[newcode 6c10be1] newcode update
1 file changed, 1 insertion(+)
bogon:project yuanjicai$ git checkout master
Switched to branch ‘master‘
bogon:project yuanjicai$ git branch
* master
newcode
bogon:project yuanjicai$ git branch -d newcode此时删除 新分支时无法删除
error: The branch ‘newcode‘ is not fully merged.
If you are sure you want to delete it, run ‘git branch -D newcode‘.
bogon:project yuanjicai$ git merge newcode合并分支
Updating 26415ad..6c10be1
Fast-forward合并类型为Fast-forward
test1.py | 1 +
1 file changed, 1 insertion(+)
bogon:project yuanjicai$
bogon:project yuanjicai$ git branch -d newcode合并分支后就可以删除newcode分支了
Deleted branch newcode (was 6c10be1).
bogon:project yuanjicai$ git branch
* master
bogon:project yuanjicai$
bogon:project yuanjicai$ git checkout -b bugfix
Switched to a new branch ‘bugfix‘
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ tail test1.py
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy‘
print ‘zzzzzzzzzzz!!!‘ #添加三个感叹号
bogon:project yuanjicai$ git commit -am ‘bug fix1‘
[bugfix eba1606] bug fix1
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ tail test1.py
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy!!!‘ #添加三个感叹号
print ‘zzzzzzzzzzz!!!‘
bogon:project yuanjicai$ git commit -am ‘bug fix2‘
print ‘hello world!!‘
[bugfix 48a5fd6] bug fix2
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git log --oneline | head -3
48a5fd6 bug fix2
eba1606 bug fix1
6c10be1 newcode update
bogon:project yuanjicai$ git checkout master
Switched to branch ‘master‘
bogon:project yuanjicai$ vim test1.py
bogon:project yuanjicai$ git commit -am ‘last update‘
[master 329577a] last update
1 file changed, 1 insertion(+), 1 deletion(-)
bogon:project yuanjicai$ git log --oneline | head -2
329577a last update
6c10be1 newcode update
bogon:project yuanjicai$ git merge bugfix #合并分支
Auto-merging test1.py
CONFLICT (content): Merge conflict in test1.py #冲突内容:合并冲突在 test1.py文件中
Automatic merge failed; fix conflicts and then commit the result. #自动合并失败;修改冲突然后提交修改后的结果
然后查看test.py源文件内容,如下
<<<<<<<< HEAD
当前分支的代码
===============
被合并分支的代码
>>>>>>>>>>>>>>>
这种冲突首先先分析两部分代码是实现相同功能而写的重复的代码,还是各自实现的不同的功能的代码。如果是重复代码:两个二选一删除一个,然后再把这些冲突标示符删除即可;如果不是重复代码,两个都需要保留,只需要把冲突符号删除即可。工程编译通过之后可以重新提交。如下所示:
bogon:project yuanjicai$ vim test1.py #删除重复代码,保留需要的部分
bogon:project yuanjicai$ git add test1.py #重新添加
bogon:project yuanjicai$ git commit -m ‘merge update‘ #重新提交
[master 2b677c0] merge update
bogon:project yuanjicai$ cat test1.py #查看修改后的代码
print ‘hello world!!‘
print ‘hello op !!‘
print ‘xxxxxxxxxxx‘
print ‘yyyyyyyyyyy!!!‘
print ‘zzzzzzzzzzz!!!‘
print ‘last line‘
bogon:project yuanjicai$ git branch -d bugfix #删除无用的分支
Deleted branch bugfix (was 48a5fd6).
bogon:project yuanjicai$ git branch #查看当前分支
* master
bogon:project yuanjicai$