手把手教你入门Git — Git使用指南(Linux)
系统:ubuntu 18.04 LTS
本文所有git命令操作实验具有连续性,git小白完全可以从头到尾跟着本文所有给出的命令走一遍,就会对git有一个初步的了解,应当能做到会用并且大致了解git的版本控制机制,遇到问题的话欢迎留言或私信博主。
git安装及配置
1 git安装
sudo apt-get install git
可通过git --version
命令查看,正常输出git版本号即安装成功。
2 配置用户名和邮箱名
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
配置完后可以通过以下命令查看
git config user.name
git config user.email
3 配置SSH公钥
创建公钥文件,生成的公钥文件会保存在本机的~/.ssh目录下。
ssh-keygen -C 'example@example.com' -t rsa
然后三步询问直接回车即可(连按三次回车)。
创建完成后进~/.ssh目录,将公钥(即id_rsa.pub的内容)复制出来。
cd ~/.ssh
cat id_rsa.pub
如果进入该目录时提示No such file or directory
,自己手动创建一个即可:mkdir ~/.ssh
。
然后来到浏览器端进行操作,首先登录自己的github账号(没有的话自行注册一个即可),进入到自己的主页,依次点击settings->SSH and GPG keys->New SSH Key
,进入到如下页面:
将刚才保存的id_rsa.pub
文件内容复制到Key
字段,Title
自己起个名字,最好是能代表当前所配置的机器的名字。然后点Add SSH key
,会要求输入当前github账号的密码,按要求输入就行了。
git本地操作
1 创建仓库并初始化
仓库(repository)也叫版本库,可以看做一个目录,这个目录里的所以文件都由Git进行管理,每个文件的修改、删除,Git都能跟踪。
-
创建一个目录
mkdir learnGit
-
将我们新创建的目录初始化为git可以管理的仓库:
cd learnGit git init
会输出
Initialized empty Git repository in /home/ps/JJ_Projects/learnGit/.git/
,表示成功初始化git仓库。这时会发现该目录中多出了一个
.git
目录,这就是git来跟踪管理版本库的。
2 添加文件
-
我们首先创建一个README文件,并写入一些内容:
touch README.txt vim README.txt # 写入 Learning Git: New File. cat README.txt # 查看文件内容 # 输出 Learning Git: New File.
-
执行
git add
命令,将文件添加的仓库。git add README.txt
这条命令不会有输出,具体作用后文会分析,这里我们先走一遍新建文件的步骤。
-
执行
git commit
命令,将文件提交的仓库。git commit -m "Submit a new file." # 双引号内是本次提交的注释,原则上可以随便写,但是尽量能表达出本次提交的改动。
会输出:
[master (root-commit) 7e21c1f] Submit a new file.1 file changed, 1 insertion(+)create mode 100644 README.txt
表示我们已经成功提交一个新文件。
3 修改文件
我们刚刚已经成功提交了一个新文件到我们的git仓库,接下来,我们来看一下怎样修改文件的内容。
-
修改文件内容
vim README.txt # 将其中内容替换为:Learning Git: Modify.
-
查看仓库状态
此时,我们可以用
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.txtno changes added to commit (use "git add" and/or "git commit -a")
意思很明显:
README.txt
文件提劲被修改过了,但是现在还没有改动需要git submit
,因为要先git add
。 -
查看文件改动
用
git diff
查看文件有哪些改动:git diff # 输出: diff --git a/README.txt b/README.txt index 5107c06..e22e629 100644 --- a/README.txt +++ b/README.txt @@ -1 +1 @@ -Learning Git: New File. +Learning Git: Modify.
即我们刚才进行的修改。
-
向上面一样,将修改添加到仓库:
git add README.txt
同样没有任何输出,但是这次我们可以用
git status
来查看一下仓库当前的状态:git status # 输出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txt
可以看到,已经有一个改动需要被commit了,可以推测add命令应该是将文件的改动放到了某个待提交的临时位置,后面会具体分析。
-
那下一步就是提交咯:
git commit -m "Modify a file." # 输出: [master a493237] Modify a file.1 file changed, 1 insertion(+), 1 deletion(-)
文件修改提交成功,我们再查看一下仓库当前状态:
git status # 输出: On branch master nothing to commit, working tree clean
我们刚刚把修改都提交了,所以现在没有东西要提交。
4 版本回退
使用git进行版本控制,重要的用途之一就是进行版本回退了,我们来看一下怎样操作。
-
我们先使用
git log
命令来查看一下仓库的修改日志:git log # 输出: commit a493237884485d9b0d6c88d64d967293ef5a80b8 (HEAD -> master) Author: user <example@example.com> Date: Wed Aug 18 20:09:27 2021 +0800Modify a file.commit 7e21c1fa1ada0c6b6dce6bef93f0c8e325d716a2 Author: user <example@example.com> Date: Wed Aug 18 19:56:17 2021 +0800Submit a new file.
显示出我们之前的两次修改操作。
我们还可以加上
--pretty=online
参数:git log --pretty=oneline # 输出: a493237884485d9b0d6c88d64d967293ef5a80b8 (HEAD -> master) Modify a file. 7e21c1fa1ada0c6b6dce6bef93f0c8e325d716a2 Submit a new file.
-
我们先查看一下当前README.txt文件中的内容:
cat README.txt # 输出: Learning Git: Modify. # 是我们上次修改文件后的内容。
使用
git reset
命令,将版本回退:git reset --hard HEAD^ # HEAD表示当前版本,HEAD^表示上一个版本,HEAD^^表示上上版本 输出: HEAD is now at 7e21c1f Submit a new file.
在查看一下版本回退之后README.txt中的内容:
cat README.txt # 输出: Learning Git: New File.
可以看到,回退到了我们修改文件之前的内容。
5 git的工作区和暂存区
在继续介绍git的本地操作之前,我们先来看一下git的版本管理究竟是怎样进行的。
概念
-
工作区(Working Directory),我们创建的learnGit 目录就是一个工作区。
-
版本库,仓库(Repository),工作区有个隐藏目录 .git ,这个不算工作区,而是 Git 的版本库。
-
版本库里面的 index(stage) 文件叫暂存区,还有Git为我们自动创建的第一个分支 master ,以及指向 master 的一个指针叫做 HEAD。
关系
前面我们提到过,如果我们想把文件添加到Git里面时,需要分两步:
第一步是用 git add
把文件添加进去,实际上就是把文件修改添加到暂存区。
第二步是用 git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。(我们现在只有唯一一个分支 master,所以现在就是往 master 分支上提交更改)
6 管理修改
git做版本控制的关键优势在于:git跟踪管理的不是文件,而是修改。
我们做这样一个实验:
-
首先,在
README.txt
中添加一行vim README.txt # 添加一行 cat README.txt # 输出: Learning Git: New File. test line 1.
-
将此次修改
add
并查看状态status
:git add README.txt git status # 输出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txtps@rong:~/JJ_Projects/learnGit$
这时我们先不提交,而是再对
README.txt
进行一次修改,按照我们之前的分析,现在我们的第一次修改应该是保存在暂存区。 -
再次修改文件
vim README.txt # 再添加一行 cat README.txt # 输出: Learning Git: New File. test line 1. test line 2.
-
不对第二次修改进行
add
,直接commit
。现在的应该是第一次修改在暂存区,第二次修改在工作区没动。git commit -m "test" # 输出: [master 611366c] test1 file changed, 1 insertion(+)
然后我们查看一下状态:
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.txtno changes added to commit (use "git add" and/or "git commit -a")
我们可以发现,第二次修改并没有被提交。
因为在工作区的第一次修改被放入暂存区,准备提交;而在工作区的第二次修改并没有被放入暂存区,所以,
git commit
命令只负责把暂存区的修改提交了。 -
提交后,我们可以用
git diff HEAD -- readme.txt
命令去查看工作区和版本库里面最新版本的区别:git diff HEAD -- README.txt # 输出: diff --git a/README.txt b/README.txt index be48ea2..0afce83 100644 --- a/README.txt +++ b/README.txt @@ -1,2 +1,3 @@Learning Git: New File.test line 1. +test line 2.
7 撤销修改
本地git的撤销修改操作有三种具体情况,分别是:
(1) 仅修改文件,没有add
,此时修改仅在工作区。
(2) 修改文件后add
过,但是没有commit
,此时修改保存在暂存区。
(3) 修改文件后,add
并commit
,此时修改已经提交到仓库。
接下来我们一个一个看。
-
仅修改文件,没有
add
,此时修改仅在工作区我们上一个实验的第二次修改只存在工作区,并未
add
,刚好符合第一种情况,这时的状态应该是这样的: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.txtno changes added to commit (use "git add" and/or "git commit -a")
其实
status
的输出信息已经提示到我们了,此时使用checkout
命令即可:git checkout -- README.txt
然后我们查看一下文件内容和状态信息:
cat README.txt # 输出: Learning Git: New File. test line 1. git status On branch master nothing to commit, working tree clean
完美撤销。
-
修改文件后
add
过,但是没有commit
,此时修改保存在暂存区我们再添加一行测试、
add
,并查看此时状态:vim README.txt # 添加一行 git add README.txt git status # 输出: On branch master Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified: README.txt
还是可以从输出信息看到,可以使用
reset
命令将放到暂存区的修改退回到工作区。git reset HEAD README.txt # 输出: Unstaged changes after reset: M README.txt 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.txtno changes added to commit (use "git add" and/or "git commit -a")
从上面的状态输出可以看到,修改已经成功地退回到工作区了。
现在就转到了情况1,再用
checkout
命令撤销就可以了。git checkout -- README.txt git status # 输出: On branch master nothing to commit, working tree clean
-
改文件后,
add
并commit
,此时修改已经提交到仓库这时已经完车了修改的提交,只能进行版本回退了,上面4已经介绍,这里不再赘述。
8 删除文件与恢复
-
我们先准备一个待删除的文件
test.txt
,并add
、commit
到仓库,这一套大家想必已经熟的不能再熟了,我们直接走一遍。touch test.txt vim test.txt # 添加内容 delete test git add test.txt git commit -m "delete test" # 输出: [master 08ffedc] delete test1 file changed, 1 insertion(+)create mode 100644 test.txt
-
在工作区中直接删除
test.py
:rm test.py
这时有两种情况:
(1) 工作区中误删文件,需要恢复
(2) 确实要删除文件,应该把删除操作提交到仓库
-
工作区中误删文件,需要恢复
这种情况其实与上面的撤销修改情况1是一样的,要将工作区的动作撤销掉,而这在我们的仓库中还是存在的,所以还是要请出我们的
checkout
命令就好了。git checkout -- test.txt ls # 输出: README.txt test.txt
可以看到,我们刚刚在工作区
rm
掉的test.txt
文件已经回来了 -
确实要删除文件,应该把删除操作提交到仓库
我们先把刚刚恢复的
test.txt
再从工作区删掉。rm test.txt
既然我们确实要删掉该文件,就直接再用
git rm
删除:git rm test.py # 输出: rm 'test.txt'
再将删除操作提交到仓库:
git commit -m "delete test" # 输出: [master 9182ef7] delete test1 file changed, 1 deletion(-)delete mode 100644 test.txt
就大功告成啦。
git远程操作
注意:远程仓库操作需要已经完成SSH公钥的配置。
新建远程仓库并关联本地仓库
- 我们先来到网页端进行操作,登录github之后,直接点绿色的小new,新建仓库。
-
网页端创建完仓库后回到本地命令行运行如下命令,添加远程仓库:
git remote add origin git@github.com:adenialzz/learngit.git
注意改成自己的用户名,这条命令不会有输出。添加后,远程库的名字就是 origin ,这是Git默认的叫法。
-
然后,我们就可以使用
git push
命令将本地仓库推到远程仓库。git push -u origin master # 输出: Counting objects: 10, done. Delta compression using up to 20 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (10/10), 816 bytes | 816.00 KiB/s, done. Total 10 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), done. remote: This repository moved. Please use the new location: remote: git@github.com:Adenialzz/learnGit.git To github.com:adenialzz/learngit.git* [new branch] master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.
因为远程库是空的,所以我们在第一次推送 master 分支时,要加上 -u 参数,Git不但会把本地的
master 分支内容推送的远程新的 master 分支,还会把本地的
master 分支和远程的 master 分支关联起来,在以后的推送或者拉取时就可以简化命令。这时,我们再到网页端查看,就可以看到我们的本地仓库的全部内容已经推倒远程仓库(当然,这里只有一个文件,因为我们的
test.txt
已经被删除掉了)。
将本地仓库推到远程
我们新建一个LICENSE.txt
文件,提交到本地仓库,并推到远程,这些操作上面到介绍过了,这里简单过一遍,
touch LICENSE.txt
vim LICENSE.txt # 添加内容
git add LICENSE.txt
git commit -m "add LICENSE"
git push origin master
需要注意的是在第一次关联过仓库之后,再推到远程时,只需git push origin master
,即可把本地 master 分支的最新修改推送至GitHub。现在,我们拥有了真正的分布式版本库。
将远程仓库拉到本地
这个应该是平时没有深入了解git之前最常用的命令了(^^),将别人的代码拉到本地。
-
点击上图的绿色的Code,将其中内容复制下来
-
在本地使用
clone
命令进行拉取:git clone https://github.com/Adenialzz/learnGit.git
git卸载
先找到git的目录:通过which git
命令,得到/usr/bin/git
。
然后完全删除该目录,并卸载git:
sudo rm -r /usr/bin/git
sudo apt-get remove git
注意要完全卸载git,以上两步缺一不可。