一、Git安装与卸载
1、安装
官网下载太慢,我们可以使用淘宝镜像下载:http://npm.taobao.org/mirrors/git-for-windowsl
下载对应的版本即可安装!安装:无脑下一步即可!
环境变量配了,就可以全局使用命令
右键git bash
配置全局,标识用户
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
git
的属于分布式的,最大的特点是,每个仓库都有一套十分完整的版本库
2、卸载
直接反安装即可、然后清理环境变量
3、GIT
-
Git Bash : Unix与Linux风格的命令行,使用最多,推荐最多
-
Git CMD : Windows风格的命令行
-
Git GUI:图形界面的Git,不建议初学者使用,尽量先熟悉常用命令
二、本地仓库操作
1、创建本地仓库
-
创建目录(尽量不是中文)或者 直接进入目录右键
git bash
$ mkdir learngit 创建一个目录 $ cd learngit 进入目录 $ pwd 查看当前路径 /Users/michael/learngit
-
初始化本地仓库使用
git init
,会在当前目录下生成.git
文件$ git init Initialized empty Git repository in /Users/michael/learngit/.git/
-
添加文件到当前创建的本地仓库,分两步:
-
使用命令
git add <file>
添加一个文件或者git add .
添加目录下所有文件,注意,可反复多次使用add,添加多个文件; -
使用命令
git commit -m "first commit(提交提示信息)"
,提交本地仓库完成。$ git commit -m "wrote a readme file" [master (root-commit) eaadf4e] wrote a readme file 1 file changed, 2 insertions(+) //一个文件改动,插入两行 create mode 100644 readme.txt
2、查看历史版本
-
要随时掌握工作区的状态,使用
git status
命令$ 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: readme.txt no changes added to commit (use "git add" and/or "git commit -a")
-
如果
git status
告诉你有文件被修改过,用git diff 文件名
可以查看修改内容(对比)当使用
add
以后,状态是be commited
,使用commit
以后,状态会是nothing to commit
-
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。 -
穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 -
要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
3、工作区和暂存区
- Git版本库里添加的时候,是分两步执行的:
-
第一步是用
git add
把文件添加进去,实际上就是把文件修改添加到暂存区; -
第二步是用
git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。-
因为我们创建Git版本库时,Git自动为我们创建了唯一一个
master
分支,所以,现在,git commit
就是往master
分支上提交更改。 -
我们在工作区创建文件后,通过
git add 文件名
,将文件加入到暂存区,此时查看状态变成未提交,通过commit -m "备注提交的信息"
,将文件加入到我们的本地仓库,提交结果会是,没有什么要提交,且工作区干净。
-
(1)、管理修改
-
第一次修改 ->
git add
-> 第二次修改 ->git commit
-
你看,我们前面讲了,Git管理的是修改,当你用
git add
命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit
只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。 -
提交后,用
git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别: -
第一次修改 ->
git add
-> 第二次修改 ->git add
->git commit
-
每次修改,如果不用
git add
到暂存区,那就不会加入到commit
中
(2)、撤销修改
-
场景1:当你改乱了工作区某个文件的内容,未进行
commit
,想直接丢弃工作区的修改时,用命令git checkout -- file
。 -
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。 -
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
(3)、删除文件
假如文件已经被你加入到暂存区,并且已经到版本库(本地仓库)以后,一般情况下,你通常直接在文件管理器中把没用的文件删除 了,或者用rm
命令删了,现在你有两个选择:
- 一是确实要从版本库中删除该文件,那就用命令
git rm
删掉,并且git commit
:那么文件就从版本库中被删除了 - 另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:使用
git checkout -- 文件名
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
三、远程仓库操作
1、设置本地与远程之间的SSH
-
本地Git仓库和Git Hub(或者码云)仓库之间的传输是通过SSH加密的:
-
创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有
id_rsa
和**id_rsa.pub**
这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:$ ssh-keygen -t rsa -C "113521@qq.com"
一路回车就行
-
登陆Git Hub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴
id_rsa.pub
文件的内容
-
2、远程仓库
-
要关联一个远程库,使用命令
git remote add origin https://gitee.com/meter-files.git(仓库地址)
;
-
关联一个远程库时必须给远程库指定一个名字,
origin
是默认习惯命名; -
关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容;第一次需要-u
,关联两个库,后面不需要-u
-
$ 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 origin master
推送最新修改; -
当你第一次使用Git的
clone
或者push
命令连接Git Hub时,会得到一个SSH警告: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)?
输入
yes
回车即可 -
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
3、删除本地与远程仓库连接
-
如果添加的时候地址写错了,或者就是想删除远程库,可以用
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
-
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到Git Hub,在后台页面找到删除按钮再删除。
2、从远程库克隆
-
要克隆一个远程仓库,首先必须知道远程仓库的地址,然后使用
git clone
命令克隆。同时建立了连接,当前目录下,会克隆到当前目录下,可以输入ls
查看下。$ git clone https://gitee.com/-files.git(仓库地址) 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支持多种协议,包括
https
,但ssh
协议速度最快。
四、分支管理
1、创建与合并分支
(1)、图解创建合并过程
master
主分支。HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。
- 创建分支以后
(dev)
,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
- 合并分支,就是直接把
master
指向dev
的当前提交,就完成了合并
(2)、具体合并操作
-
创建分支:
git branch <name>
-
切换分支:
git checkout <name>
或者git switch <name>
-
创建+切换分支:
git checkout -b <name>
或者git switch -c <name>
-
查看分支:
git branch
,当前分支前面会标*
号 -
合并某分支到当前分支:
git merge <name>
当前分支是
master
,把dev
分支的工作成果合并到master
分支上:$ git merge dev Updating d46f35e..b17d20e Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+)
-
删除分支:
git branch -d <name>
$ git branch -d dev Deleted branch dev (was b17d20e).
注意:你在dev
分支修改了文件,但是你没有提交到仓库,实际上就是相当于你在本地手动修改了这个文件,仓库并不能保存你做的改动,所以在master
分支能看到文件被改动了(相当于你没用dev
分支直接修改了这个文件一样),所以你可以用master
分支add
、commit
,对于所有分支而言, 工作区和暂存区是公共的
2、合并冲突
(1)、产生的原因
在master
主分支进行了修改并且commit
到了本地仓库,在feature1
分支上也进行了修改并且commit
到了本地仓库,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.
(2)、解决冲突
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")
-
冲突的时候可以查看
cat 文件名
冲突文件,会显示冲突文件的冲突字段,然后分别修改冲突字段vi 冲突文件名
,退出并保存,再次进行add、commit
提交:
- 用带参数的
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).
- 用带参数的
注意:合并操作( merge )只对对当前所在分支产生影响;无论是否存在冲突,合并之后,feature分支都不会发生变化
3、分支策略
-
首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; -
干活都在
dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本; -
你和你的小伙伴们每个人都在
dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
-
合并分支时,加上
--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。$ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 1 + 1 file changed, 1 insertion(+)
4、Bug分支
(1)、场景
-
正在
dev
上进行的工作还没有提交,突然来一个临时bug,创建一个分支issue-101
来修复它,Git还提供了一个stash
功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作$ git stash Saved working directory and index state WIP on dev: f52c633 add merge
-
用
git status
查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git checkout -b issue-101 Switched to a new branch 'issue-101' $ git add readme.txt $ git commit -m "fix bug 101" [issue-101 4c805e2] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-) $ git switch master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git merge --no-ff -m "merged bug fix 101" issue-101 Merge made by the 'recursive' strategy. readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
-
修复完以后,回到
dev
分支干活$ git switch dev Switched to branch 'dev' $ git status On branch dev nothing to commit, working tree clean
(2)、恢复
-
当手头工作没有完成时,先把工作现场
git stash
一下,然后去修复bug
,修复后,再git stash pop
,回到工作现场;$ git stash pop On branch dev Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: hello.py 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: readme.txt Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)
-
在
master
分支上修复的bug
,想要合并到当前dev
分支,可以用git cherry-pick <commit>
命令,把bug
提交的修改“复制”到当前分支,避免重复劳动。$ git branch * dev master $ git cherry-pick 4c805e2 [master 1d4b803] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)
5、Feature分支
(1)、场景
-
每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支
$ git switch -c feature-vulcan Switched to a new branch 'feature-vulcan' $ git add vulcan.py $ git status On branch feature-vulcan Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: vulcan.py $ git commit -m "add feature vulcan" [feature-vulcan 287773e] add feature vulcan 1 file changed, 2 insertions(+) create mode 100644 vulcan.py
-
切回
dev
,准备合并,然后删除:$ git switch dev
-
如需取消新特性,合并到dev前,直接删除分支:
$ git branch -d feature-vulcan error: The branch 'feature-vulcan' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
-
销毁失败。Git友情提醒,
feature-vulcan
分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D
参数。$ git branch -D feature-vulcan Deleted branch feature-vulcan (was 287773e).
总结 :
-
开发一个新feature,最好新建一个分支;
-
如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除。
6、多人协作
- 当你从远程仓库克隆时,实际上Git自动把本地的
master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
(1)、推送分支
-
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如
dev
,就改成:$ git push origin dev
-
master
分支是主分支,因此要时刻与远程同步; -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步; -
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
-
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
(2)、抓取分支
-
多人协作时,大家都会往
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.
当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的
master
分支。不信可以用git branch
命令看看:$ git branch * master
现在,你的小伙伴要在
dev
分支上开发,就必须创建远程origin
的dev
分支到本地,于是他用这个命令创建本地dev
分支:$ git checkout -b dev origin/dev
-
现在,他就可以在
dev
上继续修改,然后,时不时地把dev
分支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 dev 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/dev
分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:$ cat env.txt env $ git add env.txt $ git commit -m "add new env" [dev 7bd91f1] add new env 1 file changed, 1 insertion(+) create mode 100644 env.txt $ git push origin dev To github.com:michaelliao/learngit.git ! [rejected] dev -> dev (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/dev
抓下来,然后,在本地合并,解决冲突,再推送:$ git pull There is no tracking information 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> dev
git pull
也失败了,原因是没有指定本地dev
分支与远程origin/dev
分支的链接,根据提示,设置dev
和origin/dev
的链接:$ git branch --set-upstream-to=origin/dev dev Branch 'dev' set up to track remote branch 'dev' from 'origin'.
再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
,如果有冲突,要先处理冲突。
五、标签
1、创建标签
- 命令
git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个commit id; - 命令
git tag -a <tagname> -m "blablabla..."
可以指定标签信息; - 命令
git tag
可以查看所有标签。
2、操作标签
- 命令
git push origin <tagname>
可以推送一个本地标签; - 命令
git push origin --tags
可以推送全部未推送过的本地标签; - 命令
git tag -d <tagname>
可以删除一个本地标签; - 命令
git push origin :refs/tags/<tagname>
可以删除一个远程标签。
六、Gitee(码云)
简易的命令行入门教程:
-
Git 全局设置:还有SSH密钥
git config --global user.name "Jiu"; git config --global user.email "ahahahah@qq.com";
创建 git 仓库:
mkdir demo_el_back cd demo_el_back git init touch README.md git add README.md git commit -m "first commit"; git remote add origin https://gitee.com/glut/demo-el-back.git git push -u origin master
已有仓库?
cd demo_el_back git remote add origin https://gitee.com/glut/demo-el-back.git git push -u origin master
-
git分支中常用指令:
# 列出所有本地分支 git branch # 列出所有远程分支 git branch -r # 新建一个分支,但依然停留在当前分支 git branch [branch-name] # 新建一个分支,并切换到该分支 git checkout -b [branch] # 合并指定分支到当前分支 $ git merge [branch] # 删除分支 $ git branch -d [branch-name] # 删除远程分支 $ git push origin --delete [branch-name] $ git branch -dr [remote/branch]
七、示例
需求:本地有两个项目一个商家端一个配送端需要创建两个分支上传到码云上
1、首先在码云上创建项目生成两个分支(创建完项目直接去创建一个商家端分支一个配送端分支)
2、选中商家端项目 右键 选择 git bash here
3、在窗口中输入 git init 此时项目中多出一个.git文件夹
4、进入码云新建项目里,复制框里的路径
5、回到窗口输入 git remote add origin + 刚刚在码云复制的那行路径
6、输入 git pull origin master 命令,将码云上的仓库pull到本地文件夹(第一次上传的话会需要你输入码云的账号密码)
7、使用 git add . 或者git add +文件名 将文件添加到缓冲区
8、使用git commit -m '添加上传的文件描述’
9、使用git push origin master将文件上传到master
通过以上操作则把商家项目上传到分支 master上去了
二、上传配送端项目到分支 delivery上去
1、首先重复 12345步骤
2、输入 git pull origin delivery命令,将码云上的仓库pull到本地文件夹
3、输入git checkout delivery 切换分支
4、重复78步骤
5、git push
另附git教程链接
https://www.yiibai.com/git/git_pull.html
三、合并分支并上传到码云
git status
git add . 添加到本地
git commit -m ‘完成了登录退出’ 注释
git checkout master 切换到master分支
git merge login 合并login分支到maser
git push 上传到码云
四、本地分支放到云端
第一次直接git push是不行的
git push -u origin login 推送到云端login