git 学习笔记 10
start at 2023/03/09.

远端仓库-github

赶紧终结了这本书吧,这本书获取了我太多的指纹了(x

感觉 github 其实没什么好说的,就记录下一些细节吧

上传项目

上传项目分为两种,一种是新项目,另一种是现存的项目

在新建完一个仓库之后,仓库页面会提示你一些 shell 指令,上面的一部分为 create a new repository on the command line ,顾名思义就是创建一个新的项目,下面那部分正如英文的意思 push an existing repository from the command line 上传一个已存在的仓库

# 以下为新建仓库的代码
echo "# respp" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:paradoxskin/respp.git
git push -u origin main
# 以下为上传已存在仓库的代码
git remote add origin git@github.com:paradoxskin/respp.git
git branch -M main
git push -u origin main

其实可以忽略那句 git branch -M main,这句话的作用就是把当前分支的名字改成 main,之前都是默认使用 master 的,后来 github 就主张使用 main 当作主分支了,其实只是名字区别而已,使用 master 并不会有什么实质性的影响。我们不难发现两个步骤相比上面的步骤只是初始创建一个 commit 而已,而这两个步骤的最后几步是一样的

git remote add origin git@github.com:paradoxskin/respp.git

这条命令要分段来看,remote 表示这条命令是和远端相关的操作,add 是指添加字段,origin 是一个变量名,后面那串就是给这个变量名赋的值,事实上并不是一定要用 origin 的,如果从服务器上 clone 下来,默认的名称就是 origin,这只是一个惯例,使用 ggst 也是可以的(罪恶装备

git push -u origin main

这一步做了以下几件事

  1. 把 main 分支的内容推向 origin 位置
  2. 在 origin 远端服务器上,如果 main 不存在,就创建一个名为 main 的分支
  3. 如果服务器上存在 main 分支,就会移动服务器上 main 分支的位置,使它指向当前最新的进度上
  4. 设置 upstream

当然,这个命令同样不是一定要这么执行的,可以做一点变形,比如远端节点为 ggst, 我们想把 may 推上去,那么就可以使用如下命令

git push -u ggst may

这之后我们的 github 上就不再是那个指南页面了

下面解释一下命令

push 指令专门用来将本地仓库推到远端仓库

-u 表示 upstream,upstream 表示上游,看上去这个名词很难理解,其实只是另一个分支的名称而已,在 git 中每个分支都能设置一个上游,他会追踪某个分支,一般都是追踪远端服务器上的某个分支,但是要设置本地端的其他分支也可以,如果设置了 upstream, 下次执行 git push 指令的时候就会用它来当默认值,如果没有设置上游,那么每次 git push 都必须 git push origin main

和远端服务器不同的分支名

git push origin main 其实也是一个简写,写全为 git push origin main:main,意思为把本地的 main 推上去,之后在服务器上更新 main 分支,现在如果你想把本地的 master 推上远端服务器,但是创建(更新也是可以的)一个名为 cat 的分支可以用这个指令 git push origin master:cat

pull 下载

git push 相反, git pull 是用来从远端仓库拉取代码到本地更新,但是事实上 git pull 包括了两步,git fetch + git merge,拉取代码的步骤正是 git fetch,但是为什么需要 git merge 呢?那是因为在 git fetch 之后,本地的分支并没有跟着新加的 commit 移动,而远端仓库的文件相比于本地更加新,所以需要 git merge 来合并本地分支和远端分支,下面画个图展示展示

  • git fetch 之前:

before

  • git fetch 之后:

after

  • git merge 之后:

aftmerge

前面说过,合并方式除了 git merge 之外还有 git rebase,确实是存在使用 git rebasegit pull -rebase,和前面 git rebase 的优势相同,都是可以节约 merge 导致的额外 commit

push 失败

多人开发过程中,如果多人同时使用同一个分支,那么难免会遇到 push 失败的情况,这是因为 commit 是有先后的,当先 push 的人 push 之后远端仓库变成了和先 push 的人一样的状态,而后 push 的人的本地还是最早的版本,这样 push 之后就和远端仓库的历史记录发生冲突,所以就发生了错误,从而导致 push 失败,那么要如何解决呢,第一种方法是 先拉再推,在 push 前先 pull 一下,同步下远端,这里最好用 git pull -rebase,而第二种方法就有点不讲道理,直接简单粗暴地 git push -f 就能强行覆盖掉云端仓库的代码

从服务器上获取仓库

之前的 push 和 pull 都是有一个前提条件,那就是本地已经存在了这个项目,如果你在 github 上看到了某个项目,想下载来看看,那么就可以用 git clone 来复制到本地,点击 Code 按钮,复制 https 或者 ssh 链接,之后找个位置使用指令

$ git clone git@github.com:paradoxskin/respp.git

默认会用仓库名当作文件夹名,如果你想 clone 下来之后存储到不同名称的目录中,只要在后面加上目录名即可

$ git clone git@github.com:paradoxskin/respp.git ppser

当然 clone 的不止有代码,还有项目的整个历史记录、分支、标签等,直接 download zip 可是没有历史记录的哦

clone 的功能和 pull 功能很相似,区别就是当你没有项目的时候才能用 clone, 有项目就用 pull

PullRequest

上面都是 github 的基础知识了,学会就可以基本的开发了

github 上有很多开源项目,如果你看上一个有趣的项目,你想帮作者添加点新功能,然后联系作者让他给你权限,想想看,如果你是原作者,你会愿意把权限给他吗?

而 github 上就有一个不用给权限的功能,那就是 PR (Pull Request)

  1. 先把项目 fork 到自己的仓库下
  2. 因为算是自己的仓库了,所以自己拥有仓库的所有权,可以随意改动
  3. 改完后,用自己的账号 push 上去
  4. 发起 PR, 让作者知道你做了什么,让他看看
  5. 作者觉得没问题,就会将你的修改合并到他的项目中去

这是一件很有开源精神的事情(我还没做过

当然除了开源项目之外,企业内部的项目也适合使用发送 PR 的方式来开发,开发过程中,通常会挑选一个固定的分支作为可以上线的正式版本,当多人参与同一个项目的时候,为了防止事故影响正式版本,就可以通过 PR 的方式来进行开发

更新 fork 项目进度

如果在发送 PR 前,其他人的 PR 已经被接受了,那么就会发生和上文中无法 push 类似的情况,这时候解决的方法也有两种,第一种是把 fork 过来的项目删掉,再 fork 一次(

技术含量不高,但是很有用,也有很多人在用

第二种就有含金量了,使用 git remote add xxx 原仓库链接 之后可以使用 git fetch xxx 来拉取代码到本地,之后 git merge xxx/master 即可合并到最新进度,提一嘴,git remote -v 可以看到本地 remote 的所有信息

删除远端分支

一种方法是从网页上删除,这种方法很常规,另外还有一种从本地删除的方法,比如我想删除远端仓库的 cat 分支,那么可以用 push 指令来删除

$ git push origin :cat

然后本地仓库就把空的内容给推到了远端分支的 cat 分支上,所以是变相的删除了这个分支

git push -f 使用的时机

直接说结论,第一个可以使用的时机是整理历史记录,因为太乱所以决定大刀阔斧整顿一下,然后 rebase 了之后就 push -f,但记得和队友说一下,第二个可以使用的时机是只用在自己的分支上,只要不影响到其他人就好

github 为了防止有人不小心 push -f 闯了大祸就增加了一个保护功能,可以在网页中找到

当然被覆盖了其实也可以挽救,直接回到之前的进度,再次 git push -f 即可

补丁

github 很方便,但是没有 github 的时候人们是用什么来更新的呢?

答案是补丁(patch)

指定两条 commit 就可以轻松的做出从A到B的补丁文件(不包括A)

$ git format-patch startSHA1..endSHA1

使用补丁文件很简单

$ git am patch-dir/*

终于结束了这一章啊,最后还有一章 git flow, 我看看有没有必要学,如果没必要的话就到这里为止了

时间不够用不够用不够用不够用不够用啊啊啊啊啊啊啊啊啊啊

2023/03/17
> CLICK TO back <