Git 学习
config
设置用户名和账号 使用了
--global参数 表示你这台机器上的所有仓库都会用这个配置1
2git config --global user.name "Your Name"
git config --global user.email "email@example.com"查看配置
1
git config --list
创建仓库
创建文件夹
1
2mkdir learngit
cd learngit初始化仓库 初始化后会生成一个
.git目录,这个目录是隐藏的,不要手动删掉1
git init
把文件添加到仓库
1
2
3git add yourfile.txt
//或者添加所有
git add .提交到仓库
-m后面输入的是本次提交的说明,输入有意义的说明很重要1
git commit -m "wrote a yourfile.txt"
注意
-am区别1
git commit -am "xxxxx"
可以省略使用git add命令将已跟踪文件放到暂存区的功能,如果是新增的文件,处于未跟踪状态无法提交
为什么git需要
add和commit两步1
2
3git add file1.txt
git add file2.txt file3.txt
git commit -m "add 3 files"因为
commit可以一次提交很多文件,多次add不同的文件
仓库操作
git status 查看状态
- 下面表示
ztt.txt这个文件被修改过

git diff 比较修改
顾名思义就是查看文件的对比,我们可以看出第一行增加了
add content
查看完修改的内容就可以放心提交了
git commit -am "add content"
git log 查看快照
查看快照 即每次
commit后的内容,从下面可以看出我们做过两次提交,显示的顺序是从近到远
git reset 撤销
撤销已经提交到分支的恢复
让我们再修改下文件 增加一行
add footer,再查看下git log
方法一 恢复到上一个版本,
~x代表回退到上几个版本1
git reset --hard HEAD~1

方法二 恢复到未来版本 ,只要窗口没关闭的话你可以,往上找到版本号,不用写全,会自动补全(当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。)
1
git reset --hard 版本号xxx

撤销已经提交到暂存区的操作
第一步执行 文件会恢复到修改后的工作区 未添加到暂存区状态
1
git reset HEAD yourfile.txt
HEAD表示最新的版本

第二步 恢复到修改前的文件
git checkout -- yourfile.txt
git reflog 查看操作过程
用于查找
commit id,它会记录你的每一次操作
工作区和暂存区
工作区:我们存放文件的文件夹,
.git这个隐藏目录是git的版本库git版本库中最重要的称为
Stage即暂存区,git会为我们自动创建第一个分支master,以及指向master的一个指针HEAD,我们控制版本就是移动这个指针来更新文件
第一步
git add就是把文件添加到暂存区第二步
git commit就是把暂存区的内容提交到当前分支
git checkout – yourfile.txt 恢复文件
情况一 文件自修改后还没被放到暂存区,撤销修改就回到修改前的状态
情况二 文件已经添加到暂存区,又做了修改,撤销修改就回到添加到暂存区后的状态

注意命令中的
--很重要,如果没有就变成了切换到另一分支的命令
git rm 删除暂存区的文件
对应
git add的操作现在工作区新建一个
test.txt文件,并提交到分支,再在工作区手动删除文件,查看状态情况一 删除暂存区的
test.txt文件
情况二 不小心误删的,因为暂存区还有保存着一份,故可以执行以上的命令恢复文件

远程仓库
GitHub
本地Git仓库和GitHub仓库之间的传输是通过SSH加密的
创建SSH Key,在用户主目录下(cmd),查看是否存在
.ssh目录,若没有创建1
ssh-keygen -t rsa -C "youremail@example.com"

之后就可以找到
.ssh目录,其中id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露,id_rsa.pub是公钥,可以放心给别人登录Github,打开setting,选择SSH and GPG keys ,创建New SSH key


Title任意填,Key粘贴公钥里的内容即可`id_rsa.pub `添加远程库
github创建一个新的Repository

然后可以根据github提示来

在本地仓库运行命令 注意地址是你自己github的
1
git remote add origin https://github.com/yourgithub/test.git
添加后远程库的名字就是
origin,这是Git默认的叫法,可以换成别的,但是不建议,因为origin本意就是远程库推送本地内容到远程库
1
git push -u origin master
用
git push命令,实际上是把当前分支master推送到远程由于第一次推送,远程库是空的,所以加上了
-u,Git会把本地的master分支内容推送到远程新的master分支,还会把本地master分支和远程mster分支关联起来,方便以后推送和拉取可以简化命令之后只要本地做了提交,可以通过以下命令把本地
master分支最新修改推送到远程库1
git push origin master
git clone xxxx 克隆远程库到本地
- 地址可以是浏览器上的
https://xxxx - 也可以是SSH的
git@github.com:xxxx
分支管理
- 使用场景即多人协作,当你代码还没完成需要提交避免进度丢失,但是提交又会影响其他人开发时,创建自己的分支,这样就不会相互影响,等开发完毕再一次性合并到原来的分支上
创建与合并分支
原理
master分支是一条线,HEAD指向master,每次提交master分支都会向前移动一步,这样随着你不断提交master分支线会越来越长
创建
dev分支,指向master相同的提交,HEAD指向dev,从此对工作区的修改和提交都是针对dev分支,比如新提交,dev指针会往前移动一步,但是master不会移动

合并
dev到master,直接把master指向当前dev提交
合并完成之后就可以把
dev分支删除,只剩下master分支
实例
创建并切换分支到新创建的
dev分支1
git checkout -b dev
上面的相当于执行两句
1
2git branch dev
git checkout dev查看当前分支
1
git branch

增加
new.txt文件,提交到dev分支,切换到master分支看不到这个文件,这是因为这个文件提交到的是dev分支,现在切换到master分支做合并分支操作,之后可以删除dev分支1
2git checkout master
git merge dev
解决冲突
新增并切换到分支
demo1
git switch -c demo
由于git checkout 担任角色太多 既要担任切换分支又要担任恢复文件,故用以上代替 git checkout -b demo
文件
new.txt中增加一行A & B,然后提交到分支切换到
master分支,再次修改new.txt文件,增加一行A and B,然后提交分支执行
git merge demo合并分支命令,git status会有冲突提示
其中提示比远程仓库提前了2个提交Your branch is ahead of ‘origin/master’
git merge demo 是采用
Fast forward模式,禁用该模式可以加参数 git merge –no-ff -m “xxx”,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。查看
new.txt文件,Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,
修改
new.txt文件,解决冲突后提交即可,删除demo分支1
git branch -d demo
git log –graph –pretty=oneline –abbrev-commit 可以查看分支合并图
保存工作区
应用场景修复bug,但是当前你是处在分支
demo上处理问题,问题只处理到一半不能提交,但是领导要求你要先修复bug,解决方法如下保存分支
demo工作区内容,你可以多次保存1
git stash

切换到
master,创建并切换到新分支例如issue-101,修复bug,切换回master直接合并分支切换回
demo工作区继续干活,首先就要恢复工作区1
2
3
4
5
6git stash list //查看
git stash apply stash@{0} //恢复指定的位置
git stash drop //删除
git stash pop //上面两句可以用这句代替
提交
demo分支的工作复制
master刚刚修复的bug- 这是提交的
master的bug

复制master的bug
1
git cherry-pick <commit>

- 这是提交的
git branch -D 强行删除一个还没有合并的分支
多人协作
查看远程库信息
1
2git remote
git remote -v //更详细信息推送分支
1
git push origin master //远程库名字 分支也可以是dev
并不是一定要把本地分支远程推送
- master分支是主分支,因此要时刻与远程同步
- dev分支是开发分支,团队所有成员需要在上面工作,所以也需要与远程同步
- bug分支是用于本地修复bug,就没必要推送到远程了
- feature分支是否推送远程,取决于你是否和你的小伙伴合作在上面开发
git rebase
多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。
每次合并再push后,分支变成了这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/
* | 12a631b merged bug fix 101
|\ \
| * | 4c805e2 fix bug 101
|/ /
* | e1e9c68 merge with no-ff
|\ \
| |/
| * f52c633 add merge
|/
* cf810e4 conflict fixed上面看上去很乱 ,从例子看,
hello.py这个文件做了两次提交。用git log命令看看1
2
3
4
5
6
7
8
9
10
11$ git log --graph --pretty=oneline --abbrev-commit
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
...注意到Git用
(HEAD -> master)和(origin/master)标识出当前分支的HEAD和远程origin的位置分别是582d922 add author和d1be385 init hello,本地分支比远程分支快两个提交。推送本地分支
1
2
3
4
5
6
7
8
9$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.这说明有人先于我们推送了远程分支。按照经验,先pull一下:
1
2
3
4
5
6
7
8
9
10
11
12$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
d1be385..f005ed4 master -> origin/master
* [new tag] v1.0 -> v1.0
Auto-merging hello.py
Merge made by the 'recursive' strategy.
hello.py | 1 +
1 file changed, 1 insertion(+)查看状态
1
2
3
4
5
6$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean加上刚才合并的提交,现在我们本地分支比远程分支超前3个提交。
1
2
3
4
5
6
7
8
9$ git log --graph --pretty=oneline --abbrev-commit
* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/
* d1be385 init hello
...上面看起来很乱,我们使用命令整理成直线
1
2
3
4
5
6
7
8
9
10
11
12$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py再查看
1
2
3
4
5
6$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
...其实原理非常简单。我们注意观察,发现Git把我们本地的提交“挪动”了位置,放到了
f005ed4 (origin/master) set exit=1之后,这样,整个提交历史就成了一条直线。rebase操作前后,最终的提交内容是一致的,但是,我们本地的commit修改内容已经变化了,它们的修改不再基于d1be385 init hello,而是基于f005ed4 (origin/master) set exit=1,但最后的提交7e61ed4内容是一致的。rebase操作的特点:把分叉的提交历史“整理”成一条直线,看上去更直观。缺点是本地的分叉提交已经被修改过了。
最后,通过push操作把本地分支推送到远程:
1
2
3
4
5
6
7
8
9Mac:~/learngit michael$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:michaelliao/learngit.git
f005ed4..7e61ed4 master -> master再用
git log看看效果:1
2
3
4
5
6$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=1
* d1be385 init hello
...小结
- rebase操作可以把本地未push的分叉提交历史整理成直线;
- rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
标签
创建标签
切换到需要打标签的分支上,然后执行命令
1
git tag v0.1
查看所有标签
1
git tag
使用
git log查看,找到历史提交的commit id 打标签1
git tag v0.1 f52dasf
查看标签信息
1
git show v0.1
创建带有说明的标签
1
git tag -a v0.1 -m "version 0.1" 1324324
-a 表示标签名 -m 表示说明
注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
操作标签
删除标签
1
git tag -d v0.1
推送标签到远程仓库
1
git push origin v1.0
或者一次性推送所有标签
1
git push origin --tags
如果标签已经推送到远程,删除需要先删除本地,再删除远程
1
2git tag -d v0.1
git push origin :refs/tags/v0.1
使用Github
在GitHub上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送pull request给官方仓库来贡献代码