Git是目前世界上最先进的分布式版本控制系统!
先进的系统都是很人性化的,所以入门并不困难。
第一步当然是安装,Git的安装十分简单,参考:安装Git
廖大佬的这个Git教程也非常基础,适合新手入门,我这里将其精华提出,做一个快速入门。
这里是指创建本地版本库,也就是本地仓库。
在任意位置创建一个空的目录,这里注意目录路径不要包含中文。
进入创建好的目录下,打开Git Bash,执行init命令来初始化版本库:
$ git init
Initialized empty Git repository in E:/develper/test-data/git-demo2/.git/
执行成功后会在目录下多出来一个 .git 隐藏目录,到这里本地版本库就创建成功了。
当我们在版本库中有文件的修改操作时,都可以使用add
命令:
$ git add filename
例如:
新增demo.txt文件后,使用:$ git add demo.txt
修改demo.txt文件后,也可以使用:$ git add demo.txt
使用add命令后无任何提示就是成功了,可以使用status
命令查看当前工作树的状态:
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: demo.txt
从最后一行可以看出,系统发现一个新文件demo.txt,此时的demo.txt文件只是在添加到了暂存区,版本库中还没有该文件,我们还需要使用commit
命令:
$ git commit -m "create demo.txt"
[master (root-commit) 8b8daa1] create demo.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 demo.txt
commit
命令就是将暂存区的文件修改提交到版本库中,-m
是message的首字母,是为当前这次提交写入注解,与SVN中类似。
这里我们修改一下demo.txt文件,加入 hello git
,然后使用diff命令开始文件比较:
$ git diff demo.txt
diff --git a/demo.txt b/demo.txt
index e69de29..f09e9c3 100644
--- a/demo.txt
+++ b/demo.txt
@@ -0,0 +1 @@
+hello git
\ No newline at end of file
主要看倒数第二行,+表示新增的行,-表示删除的行,从这里就能看出我们对demo.txt文件新增了一行 hello git
文件修改也是使用add
命令,然后使用commit
命令提交。
当我们忘记之前提交的内容的时候,可以使用log
命令来查看历史提交记录:
$ git log
commit a8e2d4224baf763cbf54197fbe972167ecae6b97 (HEAD -> master)
Author: tanwubo
Date: Thu Feb 28 10:38:43 2019 +0800
modifier demo.txt
commit 8b8daa10dba766e2bf10d431c17f233825f69846
Author: tanwubo
Date: Thu Feb 28 10:21:02 2019 +0800
create demo.txt
这里就凸显出再使用commit
命令时的-m
参数的重要性了,我们可以通过描述信息大致了解到每一次提交的内容。
这里还有一个需要知道的,commit
后面的那一串形似密文的字符串,这个就是版本号了,由于git是分布式版本控制软件,所以并不能像svn那样使用递增数字来标识版本号。
我们通过log
命令可以查看到每次提交的版本号,通过版本号使用reset
命令可以回退到任何一个版本,像这样:
$ git reset --hard 8b8daa10dba766e2bf10d431c17f233825f69846
HEAD is now at 8b8daa1 create demo.txt
这里的--hard
参数还不太清楚其含义,后面跟的就是版本号了,当然也可以不用写全,只写部分前缀,git会自己去匹配对应的版本号,不过这里要保证前缀只能匹配到唯一一个版本号。
这里的版本号也可以使用HEAD
去代替,HEAD
会指向最近一次提交的版本,HEAD^
表示上一个版本,HEAD^^
就是上上个版本,依次类推。
当然reset
命令不仅能回退,它能将工作空间的内容变更为任何一个提交的版本,只要有版本号。
想知道自己之前做了哪些操作时,可以使用reflog
命令,像这样:
$ git reflog
8b8daa1 (HEAD -> master) HEAD@{0}: reset: moving to 8b8daa10dba766e2bf10d431c17f233825f69846
a8e2d42 HEAD@{1}: commit: modifier demo.txt
8b8daa1 (HEAD -> master) HEAD@{2}: commit (initial): create demo.txt
当自己写入了错误的内容时,可以使用git checkout -- filename
来撤销你的修改:
$ cat demo.txt
hello git
My stupid boss still prefers SVN.
$ git checkout -- demo.txt
$ cat demo.txt
hello git
注意:checkout
只能将文件撤销至上一次add
命令后,或者是上一次commit
命令后的状态。这里如果我们在修改了文件后执行了add
命令,那么这些修改是无法通过checkout
命令来撤销的。
$ cat demo.txt
hello git
My stupid boss still prefers SVN.
$ git add demo.txt
$ git checkout -- demo.txt
$ cat demo.txt
hello git
My stupid boss still prefers SVN.
当然这种情况也是可以撤销的,只不过需要多一个步骤,当文件内容修改后执行了add
命令,这里的修改就会被提交到暂存区,我们需要通过git reset HEAD filename
命令将该文件在暂存区的修改撤销掉,然后再通过git checkout -- filename
命令撤销掉工作区的修改,像这样:
$ cat demo.txt
hello git
My stupid boss still prefers SVN.
##修改已经使用add命令提交到了暂存区
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: demo.txt
$ git reset HEAD demo.txt
Unstaged changes after reset:
M demo.txt
##暂存区的修改被撤销,重新回到了工作区
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: demo.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout -- demo.txt
$ cat demo.txt
hello git
当我们需要删除一个文件时,可以手动删除,然后使用add
命令添加到暂存区,再commit
到版本库。也可以使用git rm filename
命令删除,使用rm
命令相当于手动删除文件再add
到暂存区。然后都需要使用commit
提交修改到版本库。
手动删除后使用add
命令:
$ git add rm.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
deleted: rm.txt
$ git commit -m "rm rm.txt"
[master 55e038d] rm rm.txt
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 rm.txt
使用rm
命令:
$ git rm rm.txt
rm 'rm.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
deleted: rm.txt
$ git commit -m "rm rm.txt"
[master 9975c16] rm rm.txt
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 rm.txt
当然,删除的撤销与修改的撤销是一样的,可以参考撤销修改。
以上这些都是版本控制系统的基本操作,并不属于Git的特色,但也是需要掌握的基础内容,下面来了解Git的特点。
使用码云来做远程仓库,在用户目录下的.ssh(C:\Users\username.ssh)下运行:
$ ssh-keygen -t rsa -C "[email protected]"
运行时遇到的选项直接按回车,全部使用默认值,最后会在目录下生成id_rsa
和id_rsa.pub
俩个文件,我们将id_rsa.pub
文件里面的内容贴到码云的SSH公钥中即可。
我们前面创建了一个git-demo2的本地版本库,这里我们在码云上也创建一个git-demo2的版本库,然后将俩者进行关联,就可以做远程仓库的推送、拉取了。
码云上创建新的仓库十分简单,这里不做展示,创建好之后我们通过remote
命令进行关联:
$ git remote add origin [email protected]:tanwubo/git-demo2.git
这边的地址替换成自己在码云上新建的版本库地址。
关联建立好之后,我们将本地的内容推送到码云上:
$ git push -u origin master
The authenticity of host 'gitee.com (218.11.0.86)' can't be established.
ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQp+KkGYoFgbVr17bmjey0Wc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'gitee.com,218.11.0.86' (ECDSA) to the list of knownhosts.
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (11/11), 923 bytes | 923.00 KiB/s, done.
Total 11 (delta 3), reused 0 (delta 0)
remote: Powered By Gitee.com
To gitee.com:tanwubo/git-demo2.git
* [new branch] master -> master
出现这样的信息则表示成功了。在第一次推送时记得加上-u
参数,后续的推送只需要使用:git push origin master
就可以了。
git上面的项目都会有一个类似于[email protected]:tanwubo/git-demo2.git
这样的地址,我们可以使用clone
命令复制一份版本库到本地:
$ git clone [email protected]:tanwubo/git-demo2.git
Cloning into 'git-demo2'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 14 (delta 3), reused 0 (delta 0)
Receiving objects: 100% (14/14), done.
Resolving deltas: 100% (3/3), done.
分支可以说是Git的又一大特色功能,在我们准备开发新功能时、在程序出现BUG需要修复时,我们都可以为它建立分支,并且Git无论创建、切换和删除分支,Git在1秒钟之内就能完成,并且与版本库的大小无关。
我们可以使用git checkout -b branchname
的形式来创建并切换到指定分支,像这样:
$ git checkout -b dev
Switched to a new branch 'dev'
这条指令是git branch branchname
、git checkout branchname
俩条指令的简化版,所以我们也可以这样做:
$ git branch local
$ git checkout local
Switched to branch 'local'
从这里还看不出我们切换了分支,我们可以使用git branch
来查看当前选择的分支情况:
$ git branch
dev
* local
master
然后我们对local
分支进行修改操作,并将其合并到master
分支上:
$ cat demo.txt
hello git!
local branch modifier.
$ git add demo.txt
$ git commit -m "local branch modifier"
[local 9a132bd] local branch modifier
1 file changed, 2 insertions(+), 1 deletion(-)
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ git merge local
Updating 80f6b47..9a132bd
Fast-forward
demo.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
合并后可以选择将被合并的分支删除掉:
$ git branch -d local
Deleted branch local (was 9a132bd).
$ git branch
dev
* master
这里注意,如果需要删除未合并的分支,则需要使用-D
强行删除:git branch -D local
。
当我们进行分支合并时,可能会出现修改同一个文件的情况,此时会出现合并冲突:
$ git merge dev
Auto-merging demo.txt
CONFLICT (content): Merge conflict in demo.txt
Automatic merge failed; fix conflicts and then commit the result.
出现这种提示时就是有了合并冲突了。根据提示我们查看demo.txt文件
hello git!
<<<<<<< HEAD
local branch modifier
=======
dev branch modifier
>>>>>>> dev
通过<<<<<<< HEAD
、=======
包起来的部分是当前分支的内容,======
、>>>>>>> dev
包起来的部分是dev
分支的内容,手动的选择需要的部分进行替换,然后对冲突文件再次add
、commit
即可。
$ cat demo.txt
hello git!
local branch modifier
dev branch modifier
$ git add demo.txt
$ git commit -m "solve conflict"
[master 23a4b8b] solve conflict
当我们的系统出现BUG需要修复,但是手头上的任务还未开发完,提交上去也不太合适的时候,可以通过stash
命令将工作现场进行保存,在解决完BUG后回到该分支还原保存的现场:
# 还有未提交的修改
$ git status
On branch dev
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: demo.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash
Saved working directory and index state WIP on dev: 23a4b8b solve conflict
$ git stash list
stash@{0}: WIP on dev: 23a4b8b solve conflict
# 创建BUG分支
$ git checkout -b bug-001
Switched to a new branch 'bug-001'
# 解决BUG后切换回dev分支继续开发
$ git checkout dev
Switched to branch 'dev'
# pop参数可弹出并删除最近保存的工作状态
$ git stash pop
On branch dev
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: demo.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (dc7952ffd5c944f930bf21e4bc7cf2ed162c695d)
前面的分支操作都是在本地版本库上进行的,所以我们还需要把本地分支推送给远端:
$ git push origin dev
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (15/15), 1.17 KiB | 601.00 KiB/s, done.
Total 15 (delta 2), reused 0 (delta 0)
remote: Powered By Gitee.com
To gitee.com:tanwubo/git-demo2.git
* [new branch] dev -> dev
在我们使用clone
命令复制版本库时,默认情况下只能查看到master分支:
$ git clone [email protected]:tanwubo/git-demo2.git
Cloning into 'git-demo2'...
remote: Enumerating objects: 29, done.
remote: Counting objects: 100% (29/29), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 29 (delta 5), reused 0 (delta 0)
Receiving objects: 100% (29/29), done.
Resolving deltas: 100% (5/5), done.
$ cd git-demo2/
$ git branch
* master
如果要获取远程仓库的其他分支,还需要使用这样一条命令:
$ git checkout -b dev origin/dev
Switched to a new branch 'dev'
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
$ git branch
* dev
master
注意:这里我在clone
别人的项目时,使用git checkout -b branchname origin/branchname
命令时会失败,这时需要使用git fetch
抓取一下远端版本库的信息,然后再次执行命令即可。
这部分由于条件有限,没办法演示出来了…
但是大体的流程为:
注意:这里的第五步如果当前不是master分支,很有可能会pull失败,因为本地分支没有与远端的分支建立关联,需要执行:git branch --set-upstream-to=origin/branchname branchname
后再次pull即可。
标签和分支类似,标签会绑定在某一个commit
上,并且可以为其取一个有意义的标签名。
使用tag
命令来打标签:
$ git tag v1.0
$ git tag
v1.0
还可以使用:git tag v1.0 9975c160f9320687a634d3504e035706a442e3a9
这种形式指定为某一个commit打标签。
使用show
命令来查看标签详情:
$ git show v1.0
commit 80f6b47abeddf4bd3dc377f99c8837276e33d0df (HEAD -> master, tag: v1.0, origin/master, origin/HEAD)
Author: tanwubo
Date: Thu Feb 28 14:04:23 2019 +0800
test
diff --git a/demo.txt b/demo.txt
index f09e9c3..27706f8 100644
--- a/demo.txt
+++ b/demo.txt
@@ -1 +1 @@
-hello git
\ No newline at end of file
+hello git!
\ No newline at end of file
使用-d
参数删除标签:
$ git tag
v1.0
v1.1
$ git tag -d v1.1
Deleted tag 'v1.1' (was 80f6b47)
$ git tag
v1.0
如果需要远程删除,命令较麻烦,像这样:
$ git tag -d v1.1
Deleted tag 'v1.1' (was 80f6b47)
$ git push origin :refs/tags/v1.1
remote: Powered By Gitee.com
To gitee.com:tanwubo/git-demo2.git
- [deleted] v1.1
如果需要把标签推送到远程版本库,可以像这样:
# 推送单个tag
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered By Gitee.com
To gitee.com:tanwubo/git-demo2.git
* [new tag] v1.0 -> v1.0
# 推送全部tag
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered By Gitee.com
To gitee.com:tanwubo/git-demo2.git
* [new tag] v1.1 -> v1.1