基础知识用以了解git的内部的一些原理,接下去还是看看我们平时项目中用到的一些基本命令。
1 创建仓库
创建仓库有两种方式,一种是当前目录下,通过git仓库导入所有的文件夹和文件,另一种是从远程仓库克隆出一个新的镜像仓库来。
1.1 初始化新建仓库git init,git add,git status,git commit
新建两个文件
$ echo "file 1" > a.c
$ echo "file 2" > b.c
初始化仓库git init
$ git init
Initialized empty Git repository in /home/jared/test/git/test/.git/
添加内容 git add
git add *
查看状态git status
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: a.c
new file: b.c
提交更新 git commit
$ git commit -a -m "init repo"
[master (root-commit) f348c8b] init repo
2 files changed, 2 insertions(+)
create mode 100644 a.c
create mode 100644 b.c
2 查看提交历史 git log
$ git log
commit 99e4b6cbddce4633f78fe1c2b8c07a13f068deb9
Author: jared <chenjianneng3@163.com>
Date: Mon Sep 18 14:53:05 2017 +0800
init repo
通过-p选项展开每次提交内容的差异
$ git log -p
commit 99e4b6cbddce4633f78fe1c2b8c07a13f068deb9
Author: jared <chenjianneng3@163.com>
Date: Mon Sep 18 14:53:05 2017 +0800
init repo
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..366f17f
--- /dev/null
+++ b/a.c
@@ -0,0 +1 @@
+file 1
diff --git a/b.c b/b.c
new file mode 100644
index 0000000..fac580e
--- /dev/null
+++ b/b.c
@@ -0,0 +1 @@
+file 2
通过–stat仅显示简要的增改行数统计
$ git log --stat
commit 99e4b6cbddce4633f78fe1c2b8c07a13f068deb9
Author: jared <chenjianneng3@163.com>
Date: Mon Sep 18 14:53:05 2017 +0800
init repo
a.c | 1 +
b.c | 1 +
2 files changed, 2 insertions(+)
可以通过安装gitk来查看
3 远程仓库git clone, git remote
这里使用本地新建中心仓库test1.git和test2.git来当做远程仓库。
首先clone下来:
$ git clone ~/test/repos/test1.git
Cloning into 'test1'...
done.
查看origin仓库:
$ git remote -v
origin /home/jared/test/repos/test1.git (fetch)
origin /home/jared/test/repos/test1.git (push)
添加远程仓库:
$ git remote add test2 /home/jared/test/repos/test2.git
$ git remote -v
origin /home/jared/test/repos/test1.git (fetch)
origin /home/jared/test/repos/test1.git (push)
test2 /home/jared/test/repos/test2.git (fetch)
test2 /home/jared/test/repos/test2.git (push)
要抓取所有test2 有的,但本地仓库没有的信息,可以运行 git fetch test2
$ git fetch test2
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/jared/test/repos/test2
* [new branch] master -> test2/master
* [new branch] v1.0.0 -> test2/v1.0.0
推送数据到远程仓库
$ git push origin master
Counting objects: 6, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 270 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/jared/test/repos/test1.git
7a2665e..f84af77 master -> master
4 打标签 git tag
新建标签
$ git tag -a v1.0 -m "version 1.0"
查看下
$ git tag
v1.0
分享标签,把标签分享到远程仓库:
$ git push origin v1.0
Counting objects: 1, done.
Writing objects: 100% (1/1), 151 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To /home/jared/test/repos/test1.git
* [new tag] v1.0 -> v1.0
可以通过–tags把所有标签都推送到远程仓库:
$ git push origin --tags
5 分支管理git branch, git checkout,git merge,git rebase,git cherry-pick
新建分支
$ git branch test
$ git branch -a
* master
test
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/v1.0.0
remotes/test2/master
remotes/test2/v1.0.0
切换到test分支:
$ git checkout test
Switched to branch 'test'
新建test2.c文件,并上传到test分支上
$ echo "new file" > test2.c
$ git add test2.c
$ git commit -a -m "add test2"
[test a829231] add test2
1 file changed, 1 insertion(+)
create mode 100644 test2.c
git merge使用
然后切换回master分支
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
把test分支的修改合并到master分支
$ git merge test
Updating f84af77..a829231
Fast-forward
test2.c | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test2.c
这里没有冲突,很多时候是有冲突的,解决冲突可以通过给定的提示一点一点修改。
删除分支:
$ git branch test2
$ git branch -d test2
Deleted branch test2 (was a829231).
推送本地分支到远程服务器:
$ git push origin test
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 295 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/jared/test/repos/test1.git
* [new branch] test -> test
$ git branch -a
* master
test
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/test
remotes/origin/v1.0.0
remotes/test2/master
remotes/test2/v1.0.0
git rebase使用
字面意思base是基点,rebase就是重新指向基点的意思了。同为合并提交,rebase和merge的区别就是rebase和merge产生的提交记录不同。rebase只是临时的合并,也就是还没有提交到remote的时候,要是提交到远程了,那别的小伙伴会尴尬了,各种问题也会出来了,直接用merge就好了。
看个例子:
首先有两个分支experiment和master,并且他们基于c2分别提交了c3和c4。
如果我们用merger的话,如下图所示:
$ git merge experiment
首先有两个分支experiment和master,并且他们基于c2分别提交了c3和c4。
如果我们用merger的话,如下图所示:
$ git merge experiment
直接把c3和c4合并为c5快照,然后master指向了c5,也即是把experiment的提交合并到了master分支上了。
接着看下rebase:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
这里分了两步,一步是整了一个C3‘到C4,当然C3还是存在的。
然后再把master指向了C3’了。
从图我们也可以看到merge的线不直有一个C3合并到C5中,而rebase在一条线上,看上去十分清爽。
git cherry-pick使用
cherry-pick,从字面意思来看就是挑选樱桃,可以理解为选择一个commit。比如说我有两个分支test和master,然后test和master都做了修改,然后哪天我们在test上的一次修改提交要合并到master中时。那么这个时候我们就可以使用cherry-pick了。可以看下例子。
先看下test分支的log信息
$ git log --pretty=oneline
853a7bacef381b46977ce95c1210e5367e68dde9 add test
3239e3fe98c8b2728f7e804deb5ba5cbd5f59dca add test
6fb697c388db545fac1b1ed6f333215b51768cee add test
4352023e19026005ef321959b7c7f88e467ac375 aaa Signed-off-by: chenjianneng <cjn@ka
4a3b13bf321d13b0082eac2d4e84de2e3305d26a init
通过gitk查看如下:
然后看下master分支:
$ git log --pretty=oneline
e3ce941d4a484ae122ce516c2a8f83c0db42297d add master
b8bfa7b961c034c3491da543d0763efed838ceee add master
6fb697c388db545fac1b1ed6f333215b51768cee add test
4352023e19026005ef321959b7c7f88e467ac375 aaa Signed-off-by: chenjianneng <cjn@ka
4a3b13bf321d13b0082eac2d4e84de2e3305d26a init
然后看下gitk信息:
这时想把test分支的add test的3239e3fe98c8b2728f7e804deb5ba5cbd5f59dca提交合并到master分支,就可以利用cherry-pick了
$ git cherry-pick 3239e3fe98c8b2728f7e804deb5ba5cbd5f59dca
[master c16f920] add test
1 file changed, 1 insertion(+)
create mode 100644 test.txt
然后我们合并一个有冲突的:
$ git cherry-pick 853a7bacef381b46977ce95c1210e5367e68dde9
error: could not apply 853a7ba... add test
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
冲突内容如下:
dddddd
2 <<<<<<< HEAD
3 add master
4 =======
5 add test
6 >>>>>>> 853a7ba... add test
修改好后提交:
$ git commit -a -m 'fix conflict'
[master 56a4bd5] fix conflict
1 file changed, 1 insertion(+)
总结下3中合并在什么时候用到:
git merge:侧重于把两个分支合并
git rebase: 侧重更新模块功能分支对应的基点
git cherry-pick: 侧重于把某个模块功能分支中的某次提交应用到主干分支
6 复位 git reset
首先看下提交的历史:
$ git log --pretty=oneline
07491a8695789941d9b4988b87579768b935105a add test3
a82923167649056b5e4261841cd77a6802c3f816 add test2
f84af77e2f26745a9f9e3b787f5015683713e839 test
7a2665ed82027ebab7e60053a73fe2780b0e7e3a test
6eca8005b3d45f827118a7836e03dffd041ebeec Add #test
0c59896fce377f9011e39c3f8f868a3c359ed203 init repo
然后我们切换到HEAD往前一次的提交上,但是仅仅复位提交区,工作区和阶段区的内容保持不变
$ git reset --soft HEAD~1
$ git log --pretty=oneline
a82923167649056b5e4261841cd77a6802c3f816 add test2
f84af77e2f26745a9f9e3b787f5015683713e839 test
7a2665ed82027ebab7e60053a73fe2780b0e7e3a test
6eca8005b3d45f827118a7836e03dffd041ebeec Add #test
0c59896fce377f9011e39c3f8f868a3c359ed203 init repo
这里就简单介绍下,高级用法就先不做多介绍了,用的其实也不是非常多。
7 git 配置
很多时候我们都需要配置名字和邮箱用以commit的时候用,一般会有一个global的配置:
git config --global user.name xxx
git config --global user.email xxx@@xxx
其中xxx是名字,xxx@xxx是邮箱,这个是全局的,要是是自己的电脑,基本上配置这个就够了。
如果电脑是公用的,那么就针对不同的仓库代码,自己整自己的
git config user.name xxx
git config user.email xxx@@xxx
8 配置信息.gitignore
其实很多时候我们的一些文件是不需要上传的,比如一些编译过程的文件,时刻在改变的,比如编译生成的.so库文件,.apk文件,可执行文件等等,这个时候可以通过在.gitignore中添加对应的过滤文件,git就会给它ignore掉了。
基本上也差不多把改讲的都讲了,当然还有其他的了,其实差不多知道这些,那么基本的操作啊之类就没啥问题了。
参考:
git内部原理