What & How & Why

这是本文档旧的修订版!


Git & GitHub

Git / GitHub Notes


Git

基础流程与相关命令

Git 分为三个区域:工作区暂存区版本库

  • 工作区(Working area):进行工作的区域,比如建立,编辑,分类文件等
  • 暂存区(Staging area):存放修改过的文件
  • 版本库(Repository):存储当前软件的某个正式版本
工作流程

Git 的基本工作流程是,在工作区创建好文件,然后将文件提交到暂存区;确认无误后将改动提交到版本库,作为新的版本发布:

<html>

<img src=“/_media/software_dev/ver_ctrl/git_basic_workflow.svg” width=“600”>

</html>

相关命令
  • git init:将当前的文件夹转化为 git 项目文件夹
  • git status:查看当前文件夹的中文件的状态
  • git add:将工作区的文件添加到暂存区
  • git diff:查看指定文件在工作区与暂存区之间的不同
  • git commit:将暂存区的文件提交至版本库
  • git git log:查看 commit 的历史
git diff

打印信息的例子:

#git diff output example

#white, nothing changed, indicated in white
  * @Author: Codinghare
  * @Date:   2022-05-22 21:42:56
  * @Last Modified by:   hare

#start with "-", removed or replaced, indicated in red
- * @Last Modified time: 2022-05-30 00:16:57

#start with "+", changes to the file, indicated in green.
+ * @Last Modified time: 2022-05-30 00:42:45
退出使用按键 q 即可。

git commit

git commit 有一个非常好用的 tag amend。这个 tag 允许我们对当前最新的 commit 进行更新,而不是创建一个新的 commit。这个命令在修改当前 commit 中的一些细小错误时非常有用。

当然,虽然看上去是”更新“了 commit,amand 实际上还是创建了一个新的 commit,并取代了旧的 commit(只是不会有新的 commit)记录。但终端会弹出界面要求我们重新书写 comment(-m 里写的东西)。如果要维持之前的 comment,使用下面的命令:

git commit --amend --no-edit

git log

打印信息的例子:

#SHA, unique id for the commit
commit 5f9c857051c2a9acc2036e90b4c965e16798bd6b
#Author
Author: hare <[email protected]>
#Date
Date:   Thu Jun 2 23:14:49 2022 -0600
#comments, generated by git commit -m " "
fixed typos.
一些相关的 tag:
git log --online 		  #shows the list of commits in one line format.
git log -S "keyword" 	  #displays a list of commits that contain the keyword in the message.
git log --oneline --graph #Displays a visual representation of how the branches and commits

Backtracking

BackTracking 的主要内容:

  • 将不符合要求的文件移除暂存区
  • 将工作区中被错误修改的文件回滚到未修改之前的状态
  • 将当前的 commit 回滚到之前某次的 commit

关键的概念:

  • 当前最新的 commit 被成为 HEAD commit.
  • reset 命令会更改当前的 HEAD commit 到指定的 commit
相关命令
  • git show HEAD:查看当前最新的 commit 的信息。信息额外包括了文件的变动信息。
  • git checkout HEAD取消 HEAD commit 做出的改动。
  • git checkout - -:上面命令的简化版本。
  • git reset HEAD:将 staging 区域中的文件移除
  • git reset commit_SHA:将 staging 区域中的文件重置为与 指定 SHA commit 中一致。commit_SHA 是 commit SHA 的头 7
  • git stash:将当前未完成的工作赞存入一个临时区域(临时区域可拥有多个)
  • git stash pop:取回临时区域的内容
git reset / checkout
  • git reset 通常用于暂存区中存在着不符合要求文件的情况。比如不小心将错误的源文件送至暂存区后,可以使用 reset 命令将其移除出暂存区。需要注意的是,如果指定了 commit 的 SHA,则该 commit 会成为当前的 HEAD commit。需要注意的是,reset 命令是无法取消处于工作区文件的修改的。
  • git checkout 则是对工作区的文件进行还原。当不小心修改了工作区中的文件时,可以利用该命令将其还原到 HEAD commit 时文件的状态,也就是没有被修改前的状态。
git stash

这个命令主要用于保存当前未完成的工作。比如当我们正在进行工作 A(brach A),然后接到要求去 B(branch B)进行另外工作的要求。此时我们就可以使用 git stash 将 A 这边的工作暂存;当完成 B 的工作后,回到 A,使用 git stash pop 就可以将之前未完成的工作取回,接着进行工作了。

这个命令避免了将未完成的文件进行 commit 的情形。该临时暂存的档案可以建立多个,可以通过 git stash –list 查看。

temp

  • git alias:使用该命令可以对 git 当前命令进行 alias,允许我们使用更短的命令代替原有的命令:

$ git config --global alias.co "checkout"
$ git config --global alias.br "branch"
$ git config --global alias.glop "log --pretty=format:"%h %s" --graph"

Branching

Git 允许创建不同的 branch 来对项目进行实验;也就是说,新的 branch 是作为之前版本的改动而存在的;我们可以在新的 branch 中进行开发和实验,直到功能稳定之后再合并到主要版本中,再作为新的项目版本进行发布。新的 branch 包括两部分:

  • 之前 master branch 的内容(所有 commit)
  • 新 branch 自身拥有的内容
相关命令
  • git branch:查看当前所在的 branch。
  • git branch new_branch:建立名为 new_branch 的新 branch。
  • git branch -d branch_name:删除名为 branch_name 的 branch
  • git branch -D branch_name:功能同上。如果被删除的 branch 从未合并到 master,需要使用 -D tag
  • git checkout branch_name:切换到名为 branch_name 的 branch
  • git merge branch_name:合并名为 branch_name 的 branch 到 master
merge conflict

合并 branch 到 master 的前提是,master 在 branch 新建之后没有发生改变。如果改变发生,之后再将 branch 合并回 master,会造成合并冲突(merge conflict)。这种冲突是因为 master 的不一致导致的。

当冲突发生的时候,会产生如下的信息:

Auto-merging conflict_file_name
CONFLICT (content): Merge conflict in conflict_file_name
Automatic merge failed; fix conflicts and then commit the result.
之后我们再打开冲突发生的文件,会有如下的内容:
#master version
<<<<<<< HEAD
-content of master version 
=======
#branch version
-content of branch version
>>>>>>> branch
-------------------
这一段代表了当前 masterbranch 开始时的 master 中的内容差异。我们可以选择保留当前的 master 的修改,或是保留 branch 中对应的 master 内容。但无论如何,除了要保留的内容以外,其他所有内容(包括 git 自动产生的标记)都需要删除。

Git Hub

GitHub 的简单工作流程

  1. 建立 新的 branch
  2. commit
  3. 建立 pull request
  4. 等待 reviewer 的审查通过
  5. 合并当前 branch 到 master branch,并删除当前 branch


<html>

<img src=“/_media/software_dev/ver_ctrl/github_flow.svg” width=“700”>

</html>

新建 branch 的必要性
  • 防止冲突
  • 保证主项目(master branch)不受开发进程的影响
branch 的命名方式

#author + branch type + short branch description 
hare_feature_dashboard_notifications

pull request 的注意事项
  • 提供足够的细节以便节省 review 的时间
  • PR 较小的更新,让 review 更快更容易
review 的注意事项
  • comment 应该包括需要修改的内容和原因
  • 清晰的表达自身的意思
  • 指出潜在的问题

添加 github 远程仓库

首先查找用户主目录下有没有 id_rsaid_rsa.pub 的文件,如果没有,使用以下命令生成 key(命令中的邮箱使用自己的邮箱):

ssh-keygen -t rsa -C "[email protected]"
运行以上命令后访问 .ssh 目录,会找到 id_rsaid_rsa.pub 两个文件,前者是私有密钥,需要妥善保存;后者是公有密钥,可以放心告诉别人。

接下来到 Github 中的 seting 中找到 SSH and GPG keys,将刚才生成的 id_rsa.pub 中的内容作为一个新的 SSH key 添加到 GitHub中。

添加完成之后可以输入如下命令测试是否连接成功:
ssh -T [email protected]
如果显示以下文本就证明连接成功了:
Hi XXXX! You've successfully authenticated, but GitHub does not provide shell access.
到此就可以使用 git 命令对远程库操作了。

Trouble shooting

使用 WSL 的问题
GitHub Error Message - Permission denied (publickey)

可能的解决方案:


  • 不使用 sudo 进行 Git 命令的使用

  • 如果出现以下错误:

Git XXX: fatal: could not set 'core.filemode' to 'false'
尝试修改 /etc/wsl.conf,添加以下代码(没有则创建):
[automount]
options = "metadata"
之后运行:
wsl --shutdown
重启即可


  • 如果是多用户,并出现以下错误:

fatal: Could not read from remote repository.
尝试将密钥文件夹复制给 root 一份:
sudo cp ~/.ssh/* /root/.ssh/