git学习记录

为什么需要git?

Git是什么?目前最先进的分布式版本控制系统。(linus使用c语言开发的)

什么是版本控制系统?是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的相同。

集中式vs分布式

集中式版本控制系统:版本库集中存放在中央服务器,必须联网才能工作。代表:SVN

分布式控制系统:没有“中央服务器”,每个人的电脑上都是一个完整的版本库。如何进行多人协作?将各自的修改推送给对方,就能互相看到对方的修改。优点:安全性高。

安装Git

在Linux上安装Git

在系统中输入git,通过 sudo apt-get install git就可以直接完成Git的安装;

在Windows中安装Git

在Windows上使用Git,可以直接从Git官网下载程序Git - Downloads (git-scm.com),然后安装默认选项安装即可;安装完成之后,在开始菜单里找到“Git”->"Git Bash",跳出一个类似命令行窗口的东西,说明Git安装成功!

安装完成之后,还需要最后一步设置,在命令行输入:

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

创建版本库

什么是版本库?版本库又名仓库,可以简单的理解为一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的删除、修改,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

创建版本库步骤:

第一步,选择合适的地方,创建一个空目录:

$ mkdir learngit
$ cd learngit
$ pwd
/Users/michael/learngit

pwd命令用于显示当前目录。若使用Windows系统,需要确保目录名(包括父目录)不包含中文。

第二步,通过git init命令把这个目录变成Git可以管理的仓库。

$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

如果没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah命令就可以看见。

在Windows中使用Git需要注意:千万不要使用Windows自带的记事本编辑任何文本文件。下载Visual Studio Code - Code Editing. Redefined代替记事本。

在Git中添加文件

现在编写一个readme.txt文件,内容如下:

Git is a version control system.
Git is free software.

一定要放到learngit目录下(子目录也行)!

第一步,用 git add告诉Git,把文件添加到仓库:

$ git add readme.txt

第二步,用git commit告诉Git,把文件提交到仓库:

$ 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

git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。

git commit命令执行成功后会告诉你,1 file changed:1个文件被改动(我们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。

为什么Git添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

时光穿梭机

之前已经成功添加一个readme.txt文件,现在修改readme.txt

Git is a distributed version control system.
Git is free software.

运行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 tocommit (use "git add"and/or"git commit -a")

使用git diff查看上次如何修改的readme.txt文件:(查看修改内容)

$ git diff readme.txt 
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
 Git is free software.

版本回退

现在readme.txt文件一共有三个版本被提交到Git仓库了:

版本1:wrote a readme file

Git is a version control system.
Git is free software.

版本2:add distributed

Git is a distributed version control system.
Git is free software.

版本3:append GPL

Git is a distributed version control system.
Git is free software distributed under the GPL.

使用git log命令可以查看版本控制系统的历史记录,以便确定要回退到哪个版本

$ git log
commit ec273dff4187f3282a25471ded41bde1aaa83cee (HEAD -> master)
Author: sunhairong <sunahirong@gmail.com>
Date:   Mon Mar 20 20:28:53 2023 +0800

    append GPL

commit 6dcaf4ac570d9b249b50e8a0bde341a6c1169054
Author: sunhairong <sunahirong@gmail.com>
Date:   Mon Mar 20 14:29:22 2023 +0800

    add distributed

commit 942280030d4f95b2db4b0bddc94489ca837a6906
Author: sunhairong <sunahirong@gmail.com>
Date:   Mon Mar 20 14:11:17 2023 +0800

    wrote a readme file

git log命令显示从最近到最远的提交日志

若觉得输出信息太多,可以在git log命令后加上--petty==oneline参数:

$ git log --pretty=oneline
ec273dff4187f3282a25471ded41bde1aaa83cee (HEAD -> master) append GPL
6dcaf4ac570d9b249b50e8a0bde341a6c1169054 add distributed
942280030d4f95b2db4b0bddc94489ca837a6906 wrote a readme file

ec273dff...是commit id(版本号)

现在把readme.txt回退到上一个版本,首先git要知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交ec273dff...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。

现在,我们要把当前版本append GPL回退到上一个版本add distributed,就可以使用git reset命令:

$ git reset --hard HEAD^
HEAD is now at 6dcaf4a add distributed

看看readme.txt的内容是不是版本add distributed:

$ cat readme.txt
Git is a distributed version control system.
Git is free software.

用git log再看看现在版本库的状态:

$ git log
commit 6dcaf4ac570d9b249b50e8a0bde341a6c1169054 (HEAD -> master)
Author: sunhairong <sunahirong@gmail.com>
Date:   Mon Mar 20 14:29:22 2023 +0800

    add distributed

commit 942280030d4f95b2db4b0bddc94489ca837a6906
Author: sunhairong <sunahirong@gmail.com>
Date:   Mon Mar 20 14:11:17 2023 +0800

    wrote a readme file

不过现在最新版本的append GPL已经看不到了,只要命令行窗口没有关闭,可以找到append GPL的commit id为ec273dff...,于是可以指定回到未来的某个版本:

$ git reset --hard ec273d
HEAD is now at ec273df append GPL

再次查看readme.txt的内容:

$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL:

改为指向add distributed:

然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。

现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?

在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^回退到add distributed版本时,再想恢复到append GPL,就必须找到append GPL的commit id。Git提供了一个命令git reflog用来记录你的每一次命令,以确定要回到未来哪个版本:

$ git reflog
ec273df (HEAD -> master) HEAD@{0}: reset: moving to ec273d
6dcaf4a HEAD@{1}: reset: moving to HEAD^
ec273df (HEAD -> master) HEAD@{2}: commit: append GPL
6dcaf4a HEAD@{3}: commit: add distributed
9422800 HEAD@{4}: commit (initial): wrote a readme file

工作区和暂存区

工作区:电脑里能看到的目录,比如learngit文件夹就是一个工作区

版本库:工作区有一个隐藏目录.git,是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。

把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别

$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index db28b2c..9a8b341 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
 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.
\ No newline at end of file
+Git tracks changes of files.
\ No newline at end of file

撤销修改

若在readme.txt中添加了一行:

$ cat 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.
My stupid boss still prefers SVN.

在准备提交时,发现有错误。可以删掉最后一行,手动把文件恢复到上一个版本的状态。如果用git status查看一下:

$ 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会该诉你,git restore file可以丢弃工作区的修改,同时git checkout --file (命令中的 -- 很重要,没有-- ,就变成了“切换到另一个分支”的命令也可以达到相同的效果。

以上两个命令的意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,有作了修改,现在,撤回修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。

$ git restore readme.txt

$ cat 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.

若已经将readme.txt中的内容使用git add到暂存区了,想要撤销修改:

$ cat 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.
My stupid boss still prefers SVN.

$ git add readme.txt

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

$ git restore --staged readme.txt

$ 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 restore readme.txt

$ git status
On branch master
nothing to commit, working tree clean

使用命令git restore --staged file可以把暂存区的修改撤销掉(unstage),重新放回工作区:

在使用git restore file 命令丢弃工作区的修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file或git restore file。

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>或 git restore --staged file,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

删除文件

在Git中,删除也是一个修改操作,先添加一个新文件test.txt到Git并且提交:

$ git add test.txt

$ git commit -m "add test.txt"
[master c4a0d12] add test.txt
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

一般情况下,直接会在文件管理器中把没用的文件删了,或者用rm命令删了:

$ rm test.txt

这时候,Git知道你删除了文件,因此,工作区和版本库就不一致,使用git status命令会立刻知道那些文件被删除了:

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")

现在有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:

$ git rm test.txt
rm 'test.txt'

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    test.txt

$ git commit -m "remove test.txt"
[master d509b67] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

现在,文件就从版本库中被删除了。

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- test.txt

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!

远程仓库

由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

$ ssh-keygen -t rsa -C"youremail@example.com"

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。

如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:

然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:

点“Add Key”,你就应该看到已经添加的Key。

添加远程库

现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。

首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库;

在Repository name填入learngit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库;

目前,在GitHub上的这个learngit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。

现在,我们根据GitHub的提示,在本地的learngit仓库下运行命令:

$ git remote add origin git@github.com:SHR1103/learngit.git

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

下一步,就可以把本地库的所有内容推送到远程库上:

$ git push -u origin main
Enumerating objects: 26, done.
Counting objects: 100% (26/26), done.
Delta compression using up to 12 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (26/26), 2.14 KiB | 1.07 MiB/s, done.
Total 26 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), done.
To https://github.com/SHR1103/learngit.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样;

从现在起,只要本地作了提交,就可以通过命令:

$ 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.

这个警告只会出现一次,后面的操作就不会有任何警告了。

如果你实在担心有人冒充GitHub服务器,输入yes前可以对照GitHub的RSA Key的指纹信息是否与SSH连接给出的一致。

删除远程库

如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>命令。使用前,建议先用git remote -v查看远程库信息:

$ git remote -v
origin  https://github.com/SHR1103/learngit.git (fetch)
origin  https://github.com/SHR1103/learngit.git (push)

然后,根据名字删除,比如删除origin

$ git remote rm origin

此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。

从远程库克隆

假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。

首先,登陆GitHub,创建一个新的仓库,名字叫gitskills:

勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件。

现在远程库已经准备好了,下一步用命令git clone克隆一个本地库:

$ git clone git@github.com:SHR1103/gitskills.git
Cloning into 'gitskills'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

问题:fatal: Could not read from remote repository.

解决1:

重新设置一下就好了

git config --global user.name "name"

git config --global user.email“email"

解决方案一无效,解决方案二:https://blog.csdn.net/iiiliuyang/article/details/104203197

$ git clone git@github.com:SHR1103/gitskills.git
Cloning into 'gitskills'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (6/6), done.

进入gitskills目录看一下,可以看到已经有readme.md文件了:

$ cd gitskills
$ ls
README.md

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值