现在大部分开发工具都可以直接进行菜鸟下面说的大部分操作,具体见:虽然理解git命令,但是我选择vscode插件!
还有其它文章 —— 接本文:
理解工作区和暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
工作区(Working Directory):
工作区 就是你在电脑里能看到的目录就是一个工作区:
暂存区(stage)
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库(Repository)。
Git的版本库里存了很多东西,其中最重要的就是称为stage的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
文件往Git版本库里添加的时候,是分两步执行的:
- 第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区
- 第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
这里就是为什么可以add多个文件后,一次性commit,下面
为什么Git比其他版本控制系统设计得优秀 --> 继续理解暂存区有讲!
还是实践出真理,大家可以修改一下自己的文件,然后再新建一个文本文件到工作区(暂时不用提交到git仓库),然后运行 git status 看看,菜鸟的结果如下:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
Git非常清楚地告诉我们,readme.txt 被修改了(Changes not staged),而 LICENSE 还从来没有被添加过,所以它的状态是 Untracked。
现在,使用两次命令 git add ,把 readme.txt 和 LICENSE 都添加后,用 git status 再查看一下:
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt
new file: LICENSE
如果报错
warning: LF will be replaced by CRLF in test1.txt. The file will have its original
可以不管,但是菜鸟不能让问题溜走,解决办法!
现在,暂存区的状态就变成这样了:
所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是 “干净” 的:
为什么Git比其他版本控制系统设计得优秀 --> 继续理解暂存区
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
我们还是做实验。第一步,对 readme.txt 做一个修改,比如:加一行内容,然后添加到暂存区,然后再次修改readme.txt ,最后提交到git仓库。提交后,再用git status看看状态:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
怎么第二次的修改没有被提交?
别激动,我们回顾一下操作过程:
第一次修改 -> git add -> 第二次修改 -> git commit
Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以 git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
提交后,用git diff命令可以查看工作区和版本库里面最新版本的区别:
warning: LF will be replaced by CRLF in gittwo.
The file will have its original line endings in your working directory
diff --git a/readme.txt b/readme.txt
index da64460..ab83e4f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,3 +1,3 @@
this is two git!
try change to see status!
-try xiugai!
+try guanlixiugai!
可见,第二次修改确实没有被提交。(读者修改肯定跟我不一样,所以以自己为准)
那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
看到这里,相信你一定理解了暂存区!
创建和切换分支
底下这些命令都是创建,并切换到dev分支!
git checkout -b dev
git switch -c dev
git branch dev
git checkout dev
git branch dev
git switch dev
注:
git checkout 这个命令承担了太多职责,既被用来切换分支,又被用来恢复工作区文件,对用户造成了很大的认知负担。
Git社区发布了Git的新版本2.23。在该版本中,有一个特性非常引人瞩目,就是新版本的Git引入了两个新命令 git switch 和 git restore,用以替代现在的 git checkout。
git switch 到 tag 上
git switch 还能直接跳转到 tag 上,eg:
git checkout v1.0
或者
git switch v1.0
可能会提示
If you want to detach HEAD at the commit, try again with the --detach option.
这个时候只能使用:
git checkout --detach v1.0
注:
出现这个提示一般是因为tag所在的分支被删除了!
理解分支与分叉
git remote
要查看远程库的信息,用git remote -v 显示更详细的信息:
- https
$ git remote -v
origin https://github.com/pbw-langwang/gitskills.git (fetch)
origin https://github.com/pbw-langwang/gitskills.git (push)
- ssh
$ git remote -v
origin git@github.com:pbw-langwang/gitskills.git (fetch)
origin git@github.com:pbw-langwang/gitskills.git (push)
上面显示了可以抓取(fetch)和推送(push)的origin的地址,如果没有推送权限,就看不到push的地址。
git log
git log 其实有很多参数,且不同参数能看见的东西不一样,这里菜鸟推荐一个命令(来自廖雪峰大佬):
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
其效果:
$ git lg
* =format:61fea98 - (HEAD -> master, origin/dev2) Merge branch 'dev2' of github.com:pbw-langwang/gitskills (22 hours ago) <*>
|\
| * =format:1cf6ec6 - add dev2 (23 hours ago) <*>
* | =format:5d06e73 - (origin/master, origin/HEAD) change b.txt (25 hours ago) <*>
* | =format:8a5cb29 - fix master and dev (26 hours ago) <*>
|\ \
| * \ =format:b144529 - (origin/dev) fix env conflict (27 hours ago) <*>
| |\ \
| | * | =format:13c0bba - add env (27 hours ago) <*>
| * | | =format:6b07599 - b aaddenv (27 hours ago) <*>
| |/ /
| * / =format:e0e5529 - add dev (28 hours ago) <*>
| |/
| * =format:180d386 - add b (29 hours ago) <*>
|/
* =format:036b30f - Initial commit (9 days ago) <*>
想退出直接按q就行!
.gitignore 文件注意事项
1..gitignore只能忽略那些原来没有被纳入了版本管理中的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。加入.gitignore文件时一定要先从staged移除,才可以忽略。
-
修改
.gitignore文件来列出需要忽略的文件 -
使用
git rm --cached <file>将已经被 Git 跟踪的文件从版本控制中移除,但保留本地文件
2.在使用.gitignore文件后如何删除远程仓库中以前上传的此类文件而保留本地文件?
按照1中的方式即可,然后进行commit和push,这样会发现远程仓库中的不必要文件就被删除了,以后可以直接使用git add -A来添加修改的内容,上传的文件就会受到.gitignore文件的约束。
强制添加文件
但是有时候又会出现,你添加到了.gitignore文件的文件,你又想加入进去,最简单的办法是修改.gitignore文件,如果你不想改动,就可以通过下面的办法进行添加!
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了:
$ git add gitig2.txt
The following paths are ignored by one of your .gitignore files:
gitig2.txt
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"
如果你确实想添加该文件,可以用 -f 强制添加到Git:
$ git add -f gitig.txt
通过git status查看提交状况:
$ git status
On branch dev
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: gitig.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: dev.txt
那么如果撤回会怎么样?
$ git restore --staged gitig.txt
$ git status
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: dev.txt
no changes added to commit (use "git add" and/or "git commit -a")
发现gitig.txt再次被忽略了!
查找哪里规则出错
你发现.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
$ git check-ignore -v gitig.txt
.gitignore:1:*.txt gitig.txt
Git会告诉我们,.gitignore的第1行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
GitHub远程仓库
GitHub远程仓库,这里读者自己注册GitHub账号
GitHub添加ssh
第一步:创建SSH Key。在用户主目录下(一般是:c://Users/asus/ 或者 自己全盘搜一下),看看有没有.ssh目录,如果有,再看看这个目录下有没有 id_rsa 和 id_rsa.pub 这两个文件,如果已经有了,可直接跳到下一步。如果没有,在git仓库处打开Git Bash,创建SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"
需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码 (Enter passphrase (empty for no passphrase): 不需要打密码) 。
第二步:打开GitHub
添加title,随便什么都可以。
填写key,自己的.ssh里面的id_rsa.pub文件的内容。
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以GitHub只有知道了你的公钥,就可以确认只有你自己才能推送。 --> 一般推荐https
GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
GitHub创建仓库
Repository name按照自己的git仓库起名就好,其它默认(不要选创建readme文件),然后确定。
目前,在GitHub上的这个Git_warehouse仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后把本地仓库的内容推送到GitHub仓库。
关联仓库
现在,我们根据GitHub的提示,在本地的Git_warehouse仓库下运行命令:
git remote add origin https://github.com/pbw-langwang/Git_warehouse.git (推荐)
git remote add origin git@github.com:pbw-langwang/Git_warehouse.git
注意:把上面的pbw-langwang替换成你自己的GitHub账户名,否则你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key公钥不在我的账户列表中。
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的。
然后执行:
git push -u origin master
出现输入GitHub用户名和密码界面 (https是这样,ssh菜鸟没试,如果有警告可以看看下面的SSH警告)
把本地库的内容推送到远程,用 git push 命令,实际上是把当前分支master推送到远程。由于远程库是空的,我们第一次推送master分支时,加上了 -u 参数,Git不仅会把本地的 master 分支内容推送的远程新的master 分支,还会把本地的 master 分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
刷新GitHub页面,看到远程库的内容已经和本地一模一样:
从现在起,只要本地作了提交,就可以通过命令:
git push origin master
把本地master分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!
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回车即可。(如果你是用的https,则不会警告这个)
Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts
这个警告只会出现一次,后面的操作就不会有任何警告了。
如果你实在担心有人冒充GitHub服务器,输入yes前可以对照 GitHub的RSA Key的指纹信息 是否与SSH连接给出的一致。
小结
-
要关联一个远程库,使用命令
git remote add origin https://github.com/pbw-langwang/Git_warehouse.git -
关联后,使用命令
git push -u origin master第一次推送master分支的所有内容 -
此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master推送最新修改 -
一个工作区可以关联好几个远程仓库
-
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,(SVN在没有联网的时候是拒绝干活的);当有网络的时候,再把本地提交推送一下就完成了同步