Skip to content

Git & Github 的相关指令和使用方法、笔记整理。

License

Notifications You must be signed in to change notification settings

Aldenhovel/git-handbook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 

Repository files navigation

Git 和 Github 使用方法(基本完结)

welcome

0 目录

1 Git 安装与本地的 Git 仓库管理

1.1 安装(Windows)

首先,在官网https://git-scm.com/download/win下载 Git 的Windows版安装包并安装:

az1

安装过程省略,按默认的来就可以了,完成后菜单里会多出几个 Git 的相关程序,找到 Git Bash并打开,进入命令行。由于 Git 最初是在 Linux 上用来做版本控制的工具,并不支持 MacOS,Windows 系统,所以我们使用的Git Bash是 Linux 风格移植过来的控制台,与 Windows 的 Powershell CMD 有不少区别,需要使用 Linux 的相关指令进行操作,可能需要一点 Linux 基础

首次使用我们需要为 Git 设置用户名和账号,这样才能让你的机器在分布式的仓库系统中有“身份证”,使用以下命令指定用户名和邮箱账号:

git config --global user.name "your-name"
git config --global user.email "your-email@example.com"

需要注意 --global 参数表示此机器上所有的仓库都会使用此身份配置。

返回目录

1.2 本地仓库管理

我们对于 Git 仓库的管理,比如新建、删除、同步、版本控制,都需要在 Git Bash 里面使用指令进行。在我们的硬盘里, Git 仓库和普通文件夹最本质的区别是前者有.git这个隐藏目录,.git里面存放的是关于仓库的各种信息,比如说各个版本对应的文件hooks、用户配置、暂存缓存、logs这些保证仓库正常运行的材料,一般情况下不要去修改.git的文件,以防止仓库运行出现错误:pig:。

返回目录

1.2.1 新建仓库

新建仓库的步骤是先使用mkdir新建目录,然后进入目录中使用git init将目录初始化为一个空的仓库,即增加了.git组件并设置为master分支,这样一个仓库就新建好了:

mkdir my_repo
cd my_repo && git init

az3

返回目录

1.2.2 删除仓库

因为.git是仓库管理组件,只要将.git删除就可以将它从 Git 仓库变回普通目录;如果想要连同内容一起删除,那直接删除整个仓库目录即可。在 Git Bash 中使用 rm -rf 命令移除目录:

# 删除 .git,可以看见分支提示(master)也消失了,变回普通文件夹目录
rm -rf .git/

# 删除整个my_repo仓库(包括内容),然后退回刷新内存,此时my_repo目录已经不见
rm -rf ../my_repo
cd ..

az4

az5

返回目录

2 Github 的仓库管理

...... (这个比较简单)

3 (新建)远程 Github 仓库与本地仓库关联

3.1 创建 github 仓库

首先要在 Github 中创建一个仓库,比如说Aldenhovel/git-demo,采用默认的设置就好了。

1

返回目录

3.2 创建本地仓库

然后我们在本地也创建一个仓库,在git bash中新建一个git-demo目录,然后使用:

git init

来初始化,这一步相当于新增了.git组件,把这个目录变成 git 仓库,默认的分支参数是master

2

返回目录

3.3 配置 SSH

Github 与本地的通信需要使用 SSH 来验证身份,所以要生成 SSH 密钥,在git bash中输入(记得换成你自己的邮箱):

ssh-keygen -t rsa -C "your-email@example.com"

然后回车即可得到生成的 SSH 密钥,存放在用户主目录下的.ssh下,其中生成的两个文件:

  • id_rsa 是你的私钥,注意小心保管不要泄露。
  • id_rsa.pub是公钥,我们在 Github 上提交的 SSH 密钥就是这个。

3

我们切换到对应目录下,用文本方式打开id_rsa.pub文件,将里面的内容复制下来。然后打开 Github 主页,在个人设置中找到SSH and GPG keys选项,点击New SSH key按钮:

4

将在id_rsa.pub中的公钥复制过来,可以改个名字方便管理,然后点击添加:

5

完成后就可以在列表中看到你的密钥:

6

返回目录

3.4 同步远程到本地

现在我们已经有了三大法宝:

  • 远程的 Github 仓库。
  • 本地的 Git 仓库。
  • 配置好的用于远程和本地通信的 SSH 密钥。

可以进行本地和远程的双向同步了。首先是我比较喜欢的做法:在远程创建仓库,再同步到本地,然后在本地编辑完成后推送到远程,这么做比较简单。

首先我们在 Github 上找到 Aldenhovel/git-demo 仓库的 SSH 地址(用 HTTPS 也可以),把地址复制下来:

7

前面使用git init会产生默认为master的分支,因为这是我们自己的库,我们重命名为main分支(在 Github 端新建的仓库从 2020 年 10 月开始默认主分支为 main,而在 Git 中默认为 master,如果想要将本地分支与远程仓库主分支联系则需要手动用git branch -M <new name> 将分支重命名让两边一致):

git branch -M main
# P.S git branch -M 命令执行的是强制重命名,想要新建分支,请使用 git checkout -b 命令

12

然后在git bash里面使用:

git remote add git-demo-origin git@github.com:Aldenhovel/git-demo.git

将他关联过来,这里的git-demo-origin是给远程仓库起的名,一般远程库默认叫origin(什么是origin),也可以改别的名字比如xx-origin(我的习惯):

8

这句命令的意思是将 git@github.com:Aldenhovel/git-demo.git 这个远程仓库记录为 git-demo-origin ,这样下次推送、同步就可以用简写名代替了现在本地库和远程库就产生了关联。

返回目录

4 本地库的修改,提交与远程同步

假设我们现在每日的工作是在本地库做修改,完成后再统一推送到远程,这个过程需要使用三个步骤对应三个命令 add commit push

  1. add 将新的、修改过的文件提交到本地的缓冲区。
  2. commit 将缓冲区的文件提交到本地库并完成本地更改。
  3. push 将本地库推送到远程库完成同步。

为什么需要 addcommit 分开,这是为了数据修改安全所设计的步骤逻辑,即所有修改要么一次全部改完要么完全不动,以防止修改过程中出现的突发情况导致文件部分修改而混乱(数据库的内容)。

我们尝试编辑一个readme.md文档并把它推送到 Github,随便写点东西:

10

使用add命令可以将文件添加到缓冲区,可以逐个文件添加,也可以在库的主目录下使用.将整个库添加:

git add .

然后用commit命令提交到本地库,注意-m是评论参数,你需要对你的提交加一点说明:

git commit -m "version 0.1"

最后使用push命令将本地 main 远程同步到远程仓库 git-demo-origin

git push -u git-demo-origin main

9

没有出什么差错就好:pig:。最后我们检查 Github 发现信息已经同步过去啦:

11

返回目录

5 克隆远程仓库到本地

5.1 克隆仓库

前面的是从0开始先建立 Github 仓库,再关联本地,最后在本地编辑项目并同步到本地。多数时候我们不需要从0开始建立仓库,而是在新的设备上将 Github 上的库拉下来开始上手干活。这里我们假设在本地建立一个git-demo-2仓库,并同步远程Aldenhovel/git-demo仓库。

使用git clone指令将远程仓库克隆到本地,因为我们现在已经有了一个git-demo本地库了,需要重新指定本地库名以防止冲突:

git clone git@github.com:Aldenhovel/git-demo.git git-demo-2
# git clone <远程仓库地址> <本地目录>

13

然后我们将这个新的库与Aldenhovel/git-demo远程库做关联:

git remote add git-demo-2 git@github.com:Aldenhovel/git-demo.git

14

后面就与前面的步骤一样啦,首先我们修改下readme.md

15

然后,使用add commit push 来推送同步:

git add .
git commit -m "readme.md changed"
git push -u git-demo-2 main

16

完成,没有报错:pig:,去 Github 上检查下,发现已经同步成功:

17

返回目录

5.2 选择分支

请参考 克隆某一仓库某一分支

返回目录

6 拉取最新版本的远程仓库

先说明下在 Git 指令里面 clone fetch pull 的区别:

  • clone 指令可以直接将远程仓库整个克隆过来,完全从无到有,不需要做任何init的操作。
  • fetch 指令将现有的仓库与远程的仓库做对比,将远程新的版本变化拉到本地。
  • pull 指令是 fetchmerge 的结合,将远程仓库的拉取到本地并合并。

fetchpull指令的主要区别是将远程的信息拉过来后是否需要直接合并,比较严谨的情况下,先将远程仓库fetch过来,经过检查后再merge是比较好的,但是方便起见我们直接使用pull比较多的。

返回目录

6.1 版本比较

Git 可以辨认不同的版本,但是它不是逐个文件逐字句地看你的文件,检查有没有修改来判断是否同一版本的,而是采用版本号来判断版本。以Aldenhovel/git-demo为例,在 Github 上,你的远程仓库当前版本在这个地方显示:

bb1

在本地中,可以在Git Bash中通过reflog指令来检查版本:

git reflog

bb2

返回目录

6.2 拉取最新版本

当远程或者本地的仓库经过commit提交后,仓库版本号就会变化,需要我们手动同步,由本地到远程,我们使用push方法,而从远程到本地,我们使用pull方法。

首先我们要确保远程仓库版本与本地不同,即远程仓库的版本更新,在 Github 端,我们手动改一下readme.md并提交,可以看到版本号已经变化:

bb4

使用这个命令也可以检查:

git remote show git-demo-origin
# "git-demo-origin" 这个名是之前用 git remote add 添加的,一般情况对应 origin

bb3

出现(local out of date)说明远程仓库有更新版本,可以使用pull拉取,由于从远程的 git-demo-origin 拉取到本地的 main,我们这样写:

git pull git-demo-origin main

bb5

可以看到远程的 main 分支里面对 readme.md 的修改已经被拉取到本地,在本地中打开检查下:

bb6

完成无误!:heavy_check_mark:

返回目录

6.3 提醒事项

  1. 在远程仓库不能将老的版本pull到本地(即用pull来进行版本回退),不然可能会遇到各种问题,想要在本地恢复远程仓库的版本,最好直接重新clone一个,或者采用reset --hard方法来切换回旧的版本。pull该做的就是老老实实地同步远程仓库的最新版本。
  2. 当多个分支需要合并时,直接合并内容可能会发生冲突,一般先将远程的最新的仓库pull下来,本地合并后再push上去。
  3. 注意版本号和commit,有时没有变化可能是修改的文件没有commit,导致版本号没有变化,Git 认为不需要进行操作。

返回目录

7 管理分支

Github 提倡的就是代码的开源共享,将仓库开放,人人都可以访问,大家齐心协力一起想办法解决问题(这是不是共产主义?)。因此我们或多或少都会遇到多人协同的开发情境,除了用pushpull进行本地与远程的代码同步外,多人协同开发最大的问题是合并大家的代码,这就需要在开始时产生分支,等完成后再合并到一起。本章节我们模拟新建一个分支,修改内容,然后再与主分支合并。

返回目录

7.1 新建分支

Aldenhovel/git-demo库为例,这里我们在readme.md里说明了是主分支,并且已经通过pull或者push方法将本地与远程仓库关联:

fz1

然后我们在本地新建一个dev分支:

git checkout -b dev
# 用 git checkout <name> 来切换分支, -b 为新建并切换

注意这时分支提示已经显示(dev),也可以使用git branch看到已经有了dev分支。我们将readme.md也稍作修改(记得addcommit):

fz2

这时maindev分支已经产生了不同,如果需要修改分支文件,需要先用git checkout <name>来换到对应的分支再改,因为在不同分支下,文件的内容是不同的,如下:

fz3

现在我们已经有了两个互相独立的分支,即main为主分支、dev为开发分支,我们在dev上面做自己对应部分的工作,完成后再合并到main分支上。

返回目录

7.2 合并分支Github端

假设现在我们的工作做得差不多了,需要将dev分支的内容合并到main分支,有两种思路:其一是将自己的dev分支在本地与main合并,再push上去;其二是先将dev分支push上去,再在 Github 上使用pull request合并。这里使用第二种方法:先将dev同步到 Github 上:

git push git-demo-origin dev
# 注意这里最后的参数从 main 换成 dev,即会推送到 dev 分支上

fz4

在 Github 端,我们看到 dev 已经推送上来可以访问了:

fz5

我们切换到 dev 分支,可以看到有pull request的提示,这是合并代码的入口:

fz6

进去后,可以先进行代码的对比,在这里选择将哪两个分支进行合并,如果没有冲突,会显示Able to merge的提示,点击Create pull request下一步:

fz7

在这一步中系统会做最后检查,如无意外,点击Merge pull request进行自动合并:

fz8

完成,系统会提示是否需要删除dev分支,可以直接点击删除,也可以回来在Git Bash中先把合并后的main拉下来,再使用指令将本地和远程的dev分支删除:

git checkout main
# 切换回主分支

git pull git-demo-origin main
# 同步主分支

git branch --delete dev
# 删除本地 dev 分支

git push git-demo-origin --delete dev
# 删除远程 dev 分支

fz11

此时本地和远程都只剩下合并后的 main 分支,大功告成!

返回目录

7.3 合并分支GitBash端

补充前面提到的第一种做法:将 dev 在本地与 main 合并后再 push 到远程仓库。首先在 main 分支拉取一下最新进度,然后使用 merge 或者 rebase 命令将 devmain 合并(关于合并参数) (关于merge和rebase)

bb7

没有报错,此时在本地的 main 已经成功合并了dev 分支了,然后我们需要 add, commit & pushmain 推送到远程仓库并检查,发现 main 已经成功合并了 dev 的修改内容:

bb8

bb9

最后我们选择性地删除本地 dev 分支(由于 dev 分支从头到尾都在本地新建、合并、修改,因此远程仓库里并没有 dev 分支):

git branch --delete dev

返回目录

8 版本回退

Git 的重要功能之一,版本控制可以将过去的仓库状态快速恢复出来,即版本回退。在Git Bash中,主要使用reset命令进行回退,而且还要区分soft模式和hard模式的版本回退。这里我们继续用Aldenhovel/git-demo作为示例。首先我们先commit一个旧版本version 1.0并写在readme.md中作为初始版本:

bk1

然后再commit一个version 2.0作为新版本:

bk2

通过使用reflog命令,可以查看到过去的各个版本号和注释:

git reflog

bk3

可以看到 version 1.0 的版本号为 1c0d8f4version 2.0 的版本号为 ed21741 ,目前指针指向 ed21741

返回目录

8.1 hard reset

reset --hard 是实现硬回退的指令,所谓硬回退,就是将工作目录、暂存区、历史提交全部回退到目标位置,在此位置后修改的内容全部丢失。现在我们尝试使用此命令回到 1c0d8f4 版本:

git reset --hard 1c0d8f4

bk4

可以看到指针已经指向 1c0d8f4 ,而且 readme.md 也恢复了 version 1.0 。需要说明一下的就是我们将version 2.0硬回退到version 1.0 后,前者又成了历史版本,我们同样可以使用:

git reset --hard ed21741

version 1.0 版本 “回退” 到 version 2.0 ,因此这里的 “回退” 指的是相对版本的重新载入,而不是时间倒流!

返回目录

8.2 soft reset

reset --soft 软回退相对于硬回退,最大的区别是只将版本号回退而不将工作区内容回退,即你的修改内容不会丢失,而是被放到了缓冲区,通过add & commit 又可以回到 soft reset 前的状态。

返回目录

8.3 对比 hard 和 soft reset

bk5

举个栗子,在版本 1 2 3 中, 3 是目前版本,使用 soft reset 可以退回到 2 的版本号,但对比 3 的修改会转移到缓冲区,只需要一个 commit 指令就可以重新回到 3 ;而使用 hard reset 除了版本号回退外, 3 里面所有的修改也被擦除了,只能重新编写提交。

再举个栗子,有时我们 commit 错了对象,需要重新 commit ,不需要更改内容只要将版本号回退重新 commit 即可,这时我们用 soft reset。然鹅有时我们的仓库代码出现了比较严重的漏洞,需要回退到安全版本,就需要 hard reset

除了使用版本号指定回退位置,也可以使用HEAD (什么是HEAD)^ 或者 ~ 来表示以当前版本的相对位置,例如:

git reset --hard HEAD^		回退1个版本
git reset --hard HEAD^^		回退2个版本
git reset --hard HEAD^^^	回退3个版本
......						

git reset --hard HEAD~		回退1个版本
git reset --hard HEAD~2		回退2个版本
git reset --hard HEAD~3		回退3个版本
......

返回目录

8.4 情景模拟

  1. 不小心把要创建新分支 dev 的内容提交到了 main 上:

    首先以当前 main 分支新建一个 dev 分支:

    git branch dev
    

    然后回退 main 到上一版本:

    git reset -- hard HEAD~
    

    最后切换回 newdev 分支即可:

    git checkout dev
    

    (注意此方法只针对你自己的本地仓库可行,线上随便乱回退会被队友拿来祭天吧?)

  2. 不小心把要提交到 dev 的内容提交到了 main 上:

    这时我们先软回退到 main 的上个版本,然后使用stash 将未提交内容转移到堆栈:

    git reset --soft HEAD~
    git stash
    

    然后切换回对的分支,使用 pop 弹出堆栈内容,然后 add & commit

    git checkout dev
    git stash pop
    git add .
    git commit -m "......"
    

    这样就可以啦!关于 stash 指令的说明,请看这里stash指令的作用

    返回目录

9 .gitignore

.gitignore 文件会指示每次 commit 时忽略哪些文件,一般是某些运行缓存、临时图片、或者日志,这些我们只在本地会用到,因此不需要同步到仓库里。

仓库初始化时是不包括 .gitignore 文件的,需要自己手动添加,这里我们依然使用 Aldenhovel/git-demo 仓库来演示,首先新建 .gitignore 文件,以及模拟一个 temp.log 日志文件:

ig1

由于还没有编写 .gitignore 规则,如果此时直接 add, commit & push ,临时日志文件 temp.log 也会被同步到仓库里面,因此我们在 .gitignore 中加入规则以过滤 temp.log

ig2

然后我们add, commit & push,可以看到 .gitignore 文件已经被正确同步到 Github ,而 temp.log 则按照规则被过滤,没有加入仓库:

ig3

ig4

.gitignore 规则的编写方式可以参考以下示例:

temp.log		忽略 temp.log 文件
! temp.log		不忽略 temp.log 文件
temp/			忽略 temp 文件夹
/temp			忽略根目录下的 temp 文件
temp/*			忽略 temp 文件夹内的所有内容(但文件夹本身不忽略)
temp/*.log		忽略 temp 文件夹内直接包含的所有 .log 后缀的文件(temp/xx/xx.log不受影响)
temp/**/*.log	忽略 temp 文件夹内直接及间接包含的所有 .log 后缀的文件(temp/xx/xx.log也会忽略)

返回目录

Appendix 附录

A.1 相关资料补充

  1. origin 的含义

    你的代码库 (repository) 可以存放在你的电脑里,同时你也可以把代码库托管到 Github 的服务器上。在默认情况下,origin指向的就是你本地的代码库托管在Github上的版本。使用:

    git remote -v
    

    可以查询到各个远程仓库的代号名,以及 fetch / pullpush 操作指向的远程仓库地址。使用:

    git remote add <代号> <远程仓库地址.git>
    

    可以新建本地和对应远程仓库的关联,以方便后续开发的fetch / pull push 操作。

    参考文献:https://www.php.cn/tool/git/487235.html

    返回目录 返回章节 4

  2. 克隆某一仓库某一分支

    在使用 git clone xxx.git 时,如果没有其他参数,是会把整个远程仓库克隆过来的,但是在本地只会创建出默认的 master 分支,如果需要获取仓库的某一分支,需要先使用:

    git branch -a
    

    查询可用的分支,再使用:

    $ git checkout -b <分支名> origin/<分支名>
    

    创建并加载此分支。

    参考文献:https://www.cnblogs.com/FengZeng666/p/16500352.html

    返回目录 返回章节 5.2

  3. stash指令

    设想这样一种工作情景,你在 dev 分支上开发新特性,结果突然接到 main 分支有一个问题需要立即解决,最好的做法是先将现在 dev 手头的进度(包括工作目录和暂存区)找个地方保存起来,处理完 main 再恢复出来继续做。Git 指令中的stash 指令可以基于栈来实现此想法:

    git stash 
    # 将工作目录和暂存区保存到栈中
    
    git stash save <"name">
    # 保存并起名,与 git pop <"name"> 对应
    
    git stash list
    # 展示栈中的保存列表
    
    git stash pop
    # 弹出栈顶的保存状态
    
    git stash pop <"name">
    # 弹出某版本工作状态
    
    git stash apply
    # 与 pop 相似,但不会将拿出的工作状态从栈中消除
    
    git stash clear
    # 清除之前保存的所有工作状态(慎用!)
    

    参考文献:https://blog.csdn.net/csdnlijingran/article/details/96425712

    返回目录 返回章节 8.4

  4. 提交粒度与频次

    每一次对仓库的提交不仅仅是在仓库中刷新最新的项目进度,同时也是为项目记录一个状态版本,因此采用合适的 commit 粒度与频次是很好地习惯,这可以让你在日后的检查或者需要 reset 时快速定位到对应的进度版本。具体来说,我们最好每实现一个(一组)功能就对项目发起一次 commit ,并做好对应的注释。

    返回目录

  5. 什么是HEAD

    HEAD 指向当前所在分支,类似一个活动指针,表示一个“引用”。HEAD 可以指向最新或者历史中的某个版本(即commit),当我们使用指令切换分支或者版本时,实际上就是 HEAD 在切换。

    参考文献:https://www.cnblogs.com/michael-xiang/p/13179837.html

    返回目录 返回章节 8.3

  6. 合并分支时,fast-forwardno-ff 的不同

    fast-forward 会直接将 HEAD 从主分支移动到开发分支的最新提交点上,这样不需要产生新的 commit,当然这种合并方式是有条件的,就是你的主分支上没有新的提交点(就可以把你的开发分支直接作为主分支)。

    --no-ff 是强制将主分支和开发分支通过产生新的 commit 的方式进行合并。

    如果我们没有指定 merge 的方式,默认是按照 fast-forward 合并,除非加上 --no-ff 参数,当条件不满足时,无法通过 fast-forward 方式合并成功。

    参考文献:https://www.cnblogs.com/michael-xiang/p/13179837.html

    返回目录 返回章节 7.3

  7. 关于merge指令和rebase指令

    相比于 merge 能够合并两个分支,rebase 则是将一个分支的基直接转移到另一分支对应位置上,从而保留此分支的历史提交记录,然而代价是无法像 merge 一样提交记录由时间串行,因此在实际工作中可能被禁用,更详细的解释请查阅参考文献。

    参考文献:https://www.cnblogs.com/michael-xiang/p/13179837.html

    返回目录 [返回章节 7.3](#r-merge-and rebase)

鸣谢

thanks

@松鼠 @小海狮 @四方狗

返回目录

About

Git & Github 的相关指令和使用方法、笔记整理。

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published