本篇教程基于廖雪峰教程进行的,感谢原作者,写的是目前Git教程中最优秀的 廖雪峰Git教程
Git教程
1、 Git配置安装(windows)
在Windows上使用Git,可以从Git官网直接下载安装程序,然后按默认选项安装即可。
安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功
或者在文件夹空白处右键,也会出现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IMeqqbn-1638934128878)(C:\Users\苦夏\AppData\Roaming\Typora\typora-user-images\image-20211208090626088.png)]
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
注意git config 命令的--global 参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址
2、创建版本库
- 新建文件夹,用于放置开发文件
- 通过
git init 命令把这个目录变成Git可以管理的仓库:
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
此步之后目录下会出现一个.git 的目录,这个目录是Git来跟踪管理版本库的,这个目录是默认隐藏的,但是不要去动这个文件夹的东西,不然会破坏Git仓库。
- 使用
git add 将文件添加到Git仓库
$ git add readme.txt
执行上面的命令,没有任何显示,这就对了,Unix的哲学是“没有消息就是好消息”,说明添加成功。如果是全部添加,执行git add . ,代表选中所有
- 用命令
git commit 把文件提交到仓库:
$ git commit -m "1.0.0"
-m 后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录
到此为止,你成功的在本地仓库维护了一个版本
3、关联远程仓库
推送
- 在GitHub或者Gitee等平台注册并新建仓库
- 关联远程仓库
$ git remote add origin 仓库地址
添加后,远程库的名字就是origin ,这是Git默认的叫法,也可以改成别的
- 第一次推送本地库内容到远程库
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
把本地库的内容推送到远程,用git push 命令,实际上是把当前分支master 推送到远程。
由于远程库是空的,我们第一次推送master 分支时,加上了-u 参数,Git不但会把本地的master 分支内容推送的远程新的master 分支,还会把本地的master 分支和远程的master 分支关联起来,在以后的推送或者拉取时就可以简化命令。
- 后续修改提交,就不用添加
-u
$ git push origin master
SSH警告
当你第一次使用Git的clone 或者push 命令连接GitHub时,会得到一个警告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes 回车即可。
Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
这个警告只会出现一次,后面的操作就不会有任何警告了。
删除远程仓库
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name> 命令。使用前,建议先用git remote -v 查看远程库信息:
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
然后,根据名字删除,比如删除origin :
$ git remote rm origin
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。
从远程仓库克隆
实际工作中很多时候是从远程仓库克隆
用命令git clone 克隆一个本地库:
$ git clone 克隆地址
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
分支管理
创建并合并分支
原理解析
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master 分支。HEAD 严格来说不是指向提交,而是指向master ,master 才是指向提交的,所以,HEAD 指向的就是当前分支。
一开始的时候,master 分支是一条线,Git用master 指向最新的提交,再用HEAD 指向master ,就能确定当前分支,以及当前分支的提交点:
每次提交,master 分支都会向前移动一步,这样,随着你不断提交,master 分支的线也越来越长。
当我们创建新的分支,例如dev 时,Git新建了一个指针叫dev ,指向master 相同的提交,再把HEAD 指向dev ,就表示当前分支在dev 上:
你看,Git创建一个分支很快,因为除了增加一个dev 指针,改改HEAD 的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev 分支了,比如新提交一次后,dev 指针往前移动一步,而master 指针不变:
假如我们在dev 上的工作完成了,就可以把dev 合并到master 上。Git怎么合并呢?最简单的方法,就是直接把master 指向dev 的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev 分支。删除dev 分支就是把dev 指针给删掉,删掉后,我们就剩下了一条master 分支:
实际操作
- 我们创建
dev 分支,然后切换到dev 分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout 命令加上-b 参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
用git branch 命令查看当前分支:
$ git branch
* dev
master
git branch 命令会列出所有分支,当前分支前面会标一个* 号。
- 我们就可以在
dev 分支上正常提交
$ git add readme.txt
$ git commit -m "branch test"
[dev b17d20e] branch test
1 file changed, 1 insertion(+)
dev 分支的工作完成,我们就可以切换回master 分支:
$ git checkout master
Switched to branch 'master'
切换回master 分支后,再查看一个readme.txt 文件,刚才添加的内容不见了!因为那个提交是在dev 分支上,而master 分支此刻的提交点并没有变:
- 把
dev 分支的工作成果合并到master 分支上
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge 命令用于合并指定分支到当前分支。合并后,再查看readme.txt 的内容,就可以看到,和dev 分支的最新提交是完全一样的。
注意到上面的Fast-forward 信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master 指向dev 的当前提交,所以合并速度非常快。
- 合并完成后,就可以放心地删除
dev 分支了:
$ git branch -d dev
Deleted branch dev (was b17d20e).
删除后,查看branch ,就只剩下master 分支了:
$ git branch
* master
switch
我们注意到切换分支使用git checkout <branch> ,而前面讲过的撤销修改则是git checkout -- <file> ,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch 更科学。因此,最新版本的Git提供了新的git switch 命令来切换分支:
创建并切换到新的dev 分支,可以使用:
$ git switch -c dev
直接切换到已有的master 分支,可以使用:
$ git switch master
使用新的git switch 命令,比git checkout 要更容易理解。
小结
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name> 或者git switch <name>
创建+切换分支:git checkout -b <name> 或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
解决冲突
如果你在两个分支中都进行了修改提交
现在,master 分支和feature1 分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
果然冲突了!Git告诉我们,readme.txt 文件存在冲突,必须手动解决冲突后再提交。git status 也可以告诉我们冲突的文件:
果然冲突了!Git告诉我们,readme.txt 文件存在冲突,必须手动解决冲突后再提交。git status 也可以告诉我们冲突的文件:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
我们可以直接查看readme.txt的内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
Git用<<<<<<< ,======= ,>>>>>>> 标记出不同分支的内容,我们修改如下后保存:
Creating a new branch is quick and simple.
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
现在,master 分支和feature1 分支变成了下图所示:
用带参数的git log 也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file
最后,删除feature1 分支:
$ git branch -d feature1
Deleted branch feature1 (was 14096d0).
工作完成。
小结
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph 命令可以看到分支合并图。
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev 分支上,也就是说,dev 分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev 分支合并到master 上,在master 分支发布1.0版本;
你和你的小伙伴们每个人都在dev 分支上干活,每个人都有自己的分支,时不时地往dev 分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
多人协同开发
多人协作时,大家都会往master 和dev 分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:
$ git clone git@github.com:michaelliao/learngit.git
Cloning into 'learngit'...
remote: Counting objects: 40, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 40 (delta 14), reused 40 (delta 14), pack-reused 0
Receiving objects: 100% (40/40), done.
Resolving deltas: 100% (14/14), done.
他在master ,然后,时不时地把master 分支push 到远程:
$ git add env.txt
$ git commit -m "add env"
[dev 7a5e5dd] add env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
f52c633..7a5e5dd dev -> dev
你的小伙伴已经向origin/master 分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
$ cat env.txt
env
$ git add env.txt
$ git commit -m "add new master"
[dev 7bd91f1] add new env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull 把最新的提交从origin/master 抓下来,然后,在本地合并,解决冲突,再推送:
$ git pull
There is no tracking inform$ git pull
info: detecting host provider for 'https://gitee.com/'...
info: detecting host provider for 'https://gitee.com/'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 262 bytes | 26.00 KiB/s, done.
From https://gitee.com/kuxiamuhe/branch
11d66e8..e0dfe6b master -> origin/master
error: Your local changes to the following files would be overwritten by merge:
新建文本文档.txt
Please commit your changes or stash them before you merge.
Aborting
Updating cbdab4a..e0dfe6b
ation for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> master
git pull 也失败了,原因是没有提交,通过git commit 进行一次提交以后在进行git pull
$ git pull
Auto-merging env.txt
CONFLICT (add/add): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.
这回git pull 成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:
$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict
$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
7a5e5dd..57c53ab dev -> dev
因此,多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name> 推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull 试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name> 推送就能成功!
如果git pull 提示no tracking information ,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name> 。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结
- 查看远程库信息,使用
git remote -v ; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name ,如果推送失败,先用git pull 抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name ,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name ; - 从远程抓取分支,使用
git pull ,如果有冲突,要先处理冲突。
其他见廖雪峰写的教程 https://www.liaoxuefeng.com/wiki/896043488029600
|