Learn Git

learngit

learn git

git clone git@github.com:Gzding/learngit.git

SSH 密钥

要安装 OpenSSH 才能使用 ssh,这在 Windows 中默认安装了。

执行下面命令,生成 ssh 密钥【回答yes,其他全回车就行】

1
ssh-keygen -t rsa -C "your_email@example.com"

默认在用户目录下的 .ssh 目录内生成私钥和公钥 id_rsa.pub。

本地 Git 环境配置

在Windows安装Git

略(记得配置环境变量)

设置 Git 参数

在本地配置用户名和邮箱:

1
2
git config --global user.name "name"
git config --global user.email "email"

克隆 GitHub 远程仓库

Github 的使用由于受到网络的阻碍,建议使用国内的 Gitee 更快!

但是,找项目还是 Github 中更丰富!

SSH 公钥

注册登录 GitHub,在我的设置中添加 ssh 公钥【就是[本地生成的公钥](#SSH 密钥)】。

新建仓库

在 GitHub 上 New 即可,设置仓库名和简介,并选择 Add a README file,以及 Add .gitignore文件,这样就创建好了远程仓库。

克隆仓库

克隆仓库方法有:Https 形式、SSH 形式

其中,若要后续进行 push 等操作,最好使用 SSH 形式 clone;

这样,clone 之后,remote 信息中远程仓库的地址就是 SSH 形式的;

在后续 push 等操作时,就不用进行账号密码的验证操作了!

在 GitHub 的仓库界面获得 clone 命令,在本地命令行中输入命令,克隆远程仓库。

然后就能正常使用此仓库了,其中本地和远程的 main 分支是关联的,且本地中记录了远程仓库的链接。

Token

GitHub 取消了私有仓库的账号密钥的使用,需要使用 token 才能正常访问私有仓库,token 设置流程如下:

登录自己的 GitHub 账号,在个人头像那里的设置中生成 token,路径是 Settings/Developer settings/Personal access tokens,

  • 创建新的 token
  • 设置 token name【这个就相当于账号名】
  • 设置有效期
  • 【重点】设置 token 权限,自己用就全选
  • 生成即可
  • 记得及时复制保存 token ,不然此页面一返回就看不到了

GitHub Private 的使用

创建 private 仓库后,不能像 public 仓库那样任何人都随意克隆了,private 仓库克隆方法如下:

1
git clone https://tokenName:token@github.com/githubAccount/repoName.git

使用命令查看使用过 token 的仓库中token记录:

1
git remote -v

会显示远程仓库的信息,其中就有 token 信息。

Git 仓库管理

新建本地仓库

新建本地仓库方式有:

  • 克隆远程仓库:git clone git@ip:/path/test.git
    • 推荐使用这个,免得后续添加 remote 的操作了,而且可以使用 SSH 公钥免密直接 push 等操作!
  • 初始化本地文件夹为 git 仓库:git init

新建仓库后添加的第一个文件建议为:.gitignore

  • 此文件中说明了此仓库不追踪哪些文件,也就是这些文件都会被忽略,
  • .gitignore 的内容可以在 GitHub 上创建新仓库时选择 .gitignore 类型,自动生成内容,复制一下来用就行。

Git 核心概念

git 仓库有两个区域,分别是 工作区版本库

工作区就是 .git 文件夹所在的整个文件夹,但不包括 .git 文件夹,也不包括 .gitignore 文件中声明的所有文件及文件夹;

  • 工作区中的文件可以说是当前 HEAD(见下文) 所在版本 ➕ 所有更新

版本库就是 .git 文件夹,其中分两部分:暂存区分支区

  • 暂存区:存储 git add 的所有更新,
    • git commit 时,就会把暂存区中的内容提交到当前分支,形成一个新版本;
  • 分支区:存储所有分支的所有版本。

仓库版本线

版本生成:每次提交都会向仓库中添加一个版本,每个版本都有一个 id(一串十六进制数);

查看提交记录:使用记录查看命令 git loggit log --pretty=oneline 可以查看历史提交记录;

HEAD:永远指向当前工作区所基于的版本,即:在工作区中未修改文件时,看到的所有内容都是 HEAD 所指向的版本的内容;

版本线:每个版本都是基于 HEAD ➕ 一些更新,在提交后生成的;因此,这些版本可以串成一条线;

分支:当然,有时候可以基于 HEAD 创建另外一条支线,形成分支(见下文);并且,分支在后面还能合并;如下图:

image-20240318163913152

查看:以版本线形式查看版本记录,git log --graph

更新暂存提交

更新:在仓库中,新建文件、修改文件、删除文件、重命名等都会对仓库的工作区产生更新(每个更新都是一个与 HEAD 所在版本的 diff);

查看:可以使用命令 git status 查看当前仓库的状态;可以使用命令 git log 查看历史提交记录;

暂存:使用命令 git add filename 存储此文件的更新,或者使用命令 git add . 存储所有更新

提交:当所有更新都 add 后,就可以使用命令 git commit -m "update info" 提交,此时会在 HEAD 基础上产生一个新的版本,并使 HEAD 指向此新版本;

因此,Git 的基本核心操作,几乎都是 update、add、commit。

每个更新都会可能经历以下几种状态:

  • 还没有此更新:对工作区的文件没有修改;

    • git status:nothing to commit, working tree clean
  • 已更新未暂存:对工作区中的文件修改了,但没有使用 git add 命令暂存到暂存区;

    • changes not staged for commit:
    • ​ modified: filename
  • 已更新并暂存:对工作区中的文件修改了,并且使用 git add 命令暂存到了暂存区;

    • changes to be committed:
    • ​ modified: filename
  • 已提交:此更新在暂存区时,使用了 git commit 命令,将此更新提交了。

撤销和回退

详细全面的更新撤销和版本回退的命令参考:常用命令 - 撤销 !

对于各种状态下的更新的撤销方法是:

  • 已提交的:
    • 对提交过的更新的撤销,就是版本回退!
    • 使用版本回退命令 git reset --hard id 回退至 id 标识的版本;
    • 回退后,当前工作区的内容变成 id 标识的版本刚刚被提交后的状态;
    • 但是,被回退的那些版本并不会被彻底删除,还是保存着的,
    • 还能使用 git reset --hard id 重新回到那些版本(但要记得其版本 id),
    • 记不住不用担心,git reflog 这个命令会帮你记住的!
  • 已更新并暂存的:
    • 使用命令 git restore --staged filename 将文件 filename 的暂存的更新取消暂存;
    • 但此文件的内容并不会变,只是更新的状态取消暂存了,变成了已更新未暂存;
  • 已更新未暂存的:
    • 使用命令 git restore filename 撤销此文件的新的更新;
    • 此时文件的内容就和 HEAD 版本一样了!
    • 注意,此操作不可逆的,因为此更新还未被 git 记录为一个版本!

版本切换

切换的是当前分支的当前版本!

若想回退到以前的版本,可以使用命令 git reset --hard id

记住:此命令执行时最好是在刚刚执行提交命令之后,即没有未添加和提交的更新时。

回退到上一版本:git reset --hard HEAD^

HEAD:当前最新版本,

HEAD^:上一版本,

HEAD^^:上上一版本,

回退版本之后,HEAD 指向了上一版本,上一版本就成了此时的最新版本,

但是,之前的最新版本并不会消失,只要记住其版本 id,还能使用此命令再回到那个版本;

id 记不住不用担心,git reflog 这个命令会帮你记住的!

分支管理

详细全面的命令参考:常用命令 - 分支 !

查看:使用命令 git branch 查看分支;其中当前所在分支的名字前有星号 * 标识;

新建分支git branch new-branch-name

切换分支git checkout branch-name

合并某分支到当前分支git merge branch-name

删除分支git branch -d branch-name

注意:

  • 所有未提交的更新在切换分支后还是存在的,所以切换分支之前工作区最好没有任何更新;
  • 当两个分支是不同的版本时,工作区有更新未 add 或 提交时,是切换不了分支的。
  • 因此,若有紧急事情需要立即切换到其他分支去处理,那么可以使用命令 git stash(见下文) 移出并保存当前工作区内的所有更新!

冲突处理

冲突:当将某分支合并到当前分支时,可能会产生冲突,冲突是 git 无法自主决定去留的来自两个分支的内容;

在文件中,冲突内容形式为:

  • ======= 分开,
  • 上面至 <<<<<<<< branch-name 是当前分支的内容,
  • 下面至 >>>>>>>> branch-name 是某分支的内容,

解决冲突:就是手动决定两个分支的内容的去留;

提交:手动解决好所有冲突之后,再提交一次,即将冲突的解决提交为一个新版本。

紧急任务情况

情况:当在某分支工作时,工作只做到了一半,也就是有文件处于以下状态:

  • git status : changes not staged for commit

但是,此时要立即切到其他分支处理一个紧急任务,然而当前工作区的内容还不能 add,更不能提交;

保存现场:所以,去处理紧急事件之前,需要对当前工作区未 add 的更新做些处理:

  • 使用命令 git stash 将当前工作区的未 add 的更新移除工作区并保存起来;
  • 此时,git status: nothing to commit, working tree clean

然后,就可切换分支去处理紧急事件了;待紧急事件处理后,切换到之前的工作分支继续之前的工作;

  • 但此时,git status : nothing to commit, working tree clean

恢复现场:使用命令 git stash list 查看隐藏的工作现场,

  • 使用 git stash applystash list 中的第一个取出,
  • 使用 git stash popstash list 中的第一个取出并从 stash list 中删除,
  • 使用 git stash dropstash list 中的第一个删除,

取出第一个放到工作区中,即可继续之前的工作。

协同工作

使用 Github 这个远程仓库的一个主要作用就是多人在线协作!

因此,除了本地仓库的管理,还需将工作分享给其他协作者!

远程仓库

查看:使用命令 git remote -v 查看所有管理的远程库的信息;

  • (fetch) 表示默认拉取的远程仓库
  • (push) 表示默认推送的远程仓库

添加:使用命令 git remote add name url 将以地址 url 标识的远程仓库添加到本地,并命名为 name;

删除:使用命令 git remote remove name 删除名为 name 的远程仓库;

远程分支

查看:使用命令 git branch -a 查看所有分支;使用命令 git branch -r 查看远程分支;

获取:使用命令 git fetch 拉去远程仓库的所有分支的信息;

关联:使用命令 git branch -vv 查看本地分支与远程分支关联信息;

绑定:使用命令 git branch -u remote/branch 将远程分支 remote/branch 作为当前本地分支的上游;

  • 绑定上游分支之前,需要获取到远程分支信息;
  • 绑定之后,在当前本地分支进行 pull、push 等操作时,默认从绑定的远程分支上操作。

推送拉取

拉取:使用命令 git pull remote/branch 将远程分支 remote/branch 拉取并与本地当前分支合并(可能有冲突);

获取:使用命令 git fetch 拉去远程仓库的所有分支的信息,仅仅获取,并未合并;

推送:使用命令 git push remote/branch 将本地当前分支推送到远程分支 remote/branch ,并在远程与之合并(此操作由远程仓库管理员操作);

默认:命令 git pullgit push 在本地分支有绑定的远程分支时,可以默认拉取推送。

关联远程分支

要能够 push,需要本地保存远程信息,并且将本地分支与远程的分支作链接关系,

添加远程仓库,

1
git remote add origin https://xxx/xxx/xxx.git
  • 一般将远程仓库称为 origin,但可以任意改
  • 可以添加多个远程仓库

在 Push 时,关联分支:

1
2
3
git push -u <remote "branch">

# git push -u origin "master"
  • 当本地当前分支,没有关联远程分支时,且远程没有 “branch” 这个分支时,可以使用此命令,
  • 远程会新建 master 分支,将本地要推送的分支与之关联,并进行 push,

直接关联或更改远程分支:

1
2
3
git branch -u <remote/"branch">

# git beanch -u origin/dev2 # 关联当前分支与远程分支
  • 关联之前,在本地要先知道远程存在 “branch” 分支,即要先 fetch 它一次,
1
2
3
git fecth <remote branch>

# git fetch origin dev
  • fetch 只会获得远程的最新信息,即 FETCH_HEAD ,相当于一个”指针“,这样本地就知道远程有这个分支及其最新的提交id,
  • 然后,可以对其进行其他操作,比如 设置关联、合并等;

搭建 Git 服务器

安装 Git

安装 Git 和 ssh

1
2
sudo apt-get install git
sudo apt-get install ssh

启动 Git 服务

1
service ssh start

Git 用户配置

给服务器增加管理 Git 的用户

1
2
sudo adduser git
# 可以为git用户创建用户组gits

此时,生成了用户 git 的用户文件夹:/home/git

创建 ssh 公钥管理文件

1
2
3
cd /home/git
sudo mkdir /home/git/.ssh
sudo touch /home/git/.ssh/authorized_keys

并修改此文件的权限和所属权

1
2
3
4
5
6
sudo chmod 700 /home/git
sudo chmod 700 /home/git/.ssh
sudo chmod 600 /home/git/authorized_keys
sudo chown -R git:git /home/git
sudo chown -R git:git /home/git/.ssh
sudo chown -R git:git /home/git/.ssh/authorized_keys

创建仓库路径

1
2
sudo mkdir github # 此路径在/home/git中创建
sudo chown git:git github

安全处理

禁止 git 用户登录服务器

先使用下命令找到 git-shell 的位置

1
2
which git-shell
# 比如 /usr/local/git/bin/git-shell

修改/etc/passwd中的内容

1
vim /etc/passwd

git:x:1004:1004:,,,:/home/git:/bin/bash 修改成 git:x:1004:1004:,,,:/home/git:/usr/local/git/bin/git-shell,其中的路径就是刚刚查到的。

添加 SSH 公钥

使用 root 操作

将本地生成的公钥复制到服务器上的 /home/git/.ssh/authorized_keys文件中。

新建空白仓库

使用 root 操作,但要设置所属权!

1
2
3
cd /home/git/github
sudo git init --bare test.git
sudo chown -R git:gits test.git # 用户:用户组

此 test.git 仓库的地址就是:git@ip:/home/git/github/test.git;

然后,就可以在本地克隆此仓库,并正常使用了。