[学习笔记]Git教程-整理自廖雪峰的官方网站-2024年重新编辑版

更新时间:
2024.6.20:重新复习了一下Git,并整理了Git命令到另一个博客

参考资料:

廖雪峰的官方网站-Git:https://www.liaoxuefeng.com/wiki/896043488029600

1.安装Git

1.1在windows上安装Git

  • 在Git官网:https://git-scm.com/downloads找到安装包并完成安装。
  • 安装完成后,右键-git-git bash here可以打开git命令行
  • 设置用户名和密码
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
  • 查看设置的用户名和密码
$ git config --list

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

2.创建版本库

1.为什么Git比其他版本控制系统设计得更优秀?因为Git跟踪并管理的是修改,而非文件。
2.Git在有些情形下不区分大小写,在有些情形下区分大小写,所以尽可能严格按大小写来
3.如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。

  • 使用git init命令可以初始化一个Git版本库。
  • 添加文件到Git版本库分两步:
    1.使用git add <file>命令可以将文件提交到暂存区。
    2.使用git commit -m "message"命令可以将文件从暂存区提交到版本库。

可以多次使用git add <file>命令添加多个文件
可以使用git add .命令添加目录下的所有文件
git commit命令的-m参数后面输入的是本次提交的说明。
git init是一种初始化版本库的方法,还有一种方法是git clone,可以将github上别人开源的代码克隆到本地并进行版本管理。

$ git clone https://github.com/jquery/jquery.git

3.时光机穿梭

  • 使用git status命令可以查询工作区状态:文件是否修改,是否进入暂存区。
  • 使用git diff命令可以查看修改内容。

git diff是查看diffference,显示的格式是Unix通用的diff格式。

3.1版本回退

  • 在Git中,用HEAD指向当前版本,HEAD^指向上个版本,HEAD^^指向上上个版本,HEAD~100指向往上数100个版本。
  • 使用命令git reset --hard HEAD^可以回到上个版本
  • 也可以使用命令git reset --hard commit_id在版本间穿梭
  • 穿梭前,可以使用git log命令查看提交历史,以便确定要回退的版本。
  • 要重返未来,可以用git reflog查看命令历史,以便确定未来版本的版本号。

git log命令显示从最近到最远的提交日志
形如commit 9fa66a...的是commit id(版本号)
可以在git log命令后面加上--pretty=oneline参数,这样输出的内容会比较简略
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD的指向改变,并把工作区的文件更新
版本号没必要写全,一般只需要写前5-7位即可

3.2工作区和暂存区

  • 版本库(Repository):隐藏目录.git,它是Git的版本库。
  • 工作区(Working Directory):除.git外的文件和目录属于工作区。
  • 版本库里有三个东西非常重要:
    1.暂存区(Stage/Index):git add命令就是将文件提交到暂存区。
    2.master分支:创建Git版本库时,Git会自动创建唯一一个master分支。
    3.HEAD指针:GIt会自动创建一个一开始指向master的HEAD指针。
    在这里插入图片描述

3.3管理修改

  • Git跟踪并管理的是修改,而非文件
  • 每次修改,如果不用git add添加到暂存区,则不会加入到commit

3.4撤销修改

  • 使用git restore [--source=<>] [--staged] [--worktree] <pathspec>命令(参考git restore文档
  • 在未指定source的情况下
    – 如果有”--staged‘和”--worktree“,则将’HEAD’的内容恢复到工作区和暂存区
    –如果只有“--staged”,则将’HEAD’的内容恢复到暂存区
    –如果只用”--worktree“,则将暂存区(’index‘)的内容恢复到工作区
    –如果没有”--staged‘和”--worktree“,则默认将暂存区(’index‘)的内容恢复到工作区
  • 在指定source的情况下,则恢复源为source表示的版本库的内容
    在这里插入图片描述

如果恢复源是暂存区,但暂存区没有内容,其实表示暂存区和HEAD是一致的,则从HEAD恢复内容,如果恢复源是暂存区,但是暂存区没有内容,会报错pathspec 'readme.txt' did not match any file(s) known to git

# 几个例子
git restore --staged readme.txt # 会将HEAD的内容恢复到暂存区
git restore readme.txt # 会将暂存区的内容恢复到工作区
git restore --source HEAD --staged readme.txt # 会将HEAD的内容恢复到暂存区
git restore --source 17539a readme.txt # 会将”17539a“标识的版本的内容恢复到工作区
git restore --staged --worktree readme.txt # 会将HEAD的内容恢复到暂存区和工作区

几个场景:

  • 场景1:如果修改了文件,但还没有提交到暂存区,想将HEAD(暂存区)的内容恢复到工作区
git restore readme.txt
  • 场景2:如果修改了文件,但已经提交到暂存区了,想将HEAD的内容恢复到暂存区和工作区
# 方法一:先将HEAD恢复到暂存区,再将暂存区恢复到工作区
git restore --staged readme.txt
git retore readme.txt
# 方法二:同时将HEAD恢复到暂存区和工作区
git restore --staged --worktree readme.txt
  • 场景3:如果修改了文件,且已经提交到版本库了,想将上个版本的内容恢复到当前HEAD
# 直接版本回退
git reset --hard HEAD^

3.5删除文件

  • 在Git中,删除也是一个修改操作。
  • 添加一个新文件test.txt,并提交到版本库。
  • 使用"git rm test.txt"命令:可以删除工作区的test.txt文件,同时将此次删除操作提交到暂存区,然后只需要commit,则版本库中test.txt文件也删除了。
git rm test.txt
git commit -m "remove test.txt"
  • 如果版本库中还有test.txt文件,则可以使用”git restore“命令撤销删除。
git restore --staged test.txt # 从版本库恢复test.txt文件到暂存区
git restore test.txt

注意这里不能直接使用"git restore test.txt"恢复test.txt文件,因为暂存区已经没有test.txt文件了
从来没有被添加到版本库就被删除的文件,是无法恢复的

4.远程仓库

Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。
一般是找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
GitHub就可以提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。

  • 第一步:使用以下命令生成SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"  

后面的your_email@youremail.com改为你在 Github 上注册的邮箱,之后会要求确认路径和输入密码,使用默认的一路回车即可。
这样就会在家目录~/下生成.ssh目录,里面有id_rsaid_rsa.pub两个文件,前者是私钥(不能泄露),后者是公钥

  • 第二步:登陆Github,打开account=>settings,左边选择SSH and GPG keys,点击New SSH key按钮,title随便填,在文本框内粘贴id_rsa.pub文件中的内容。点击“Add Key”。

为什么Github需要SSH Key,因为因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。

4.1添加远程库

  • 在Github上创建一个名为learngit的仓库
    在这里插入图片描述

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

  • 在本地的learngit仓库下运行命令:
$ git remote -v # 查看远程库的信息
$ git remote rm origin # 删除关联的origin远程库
$ git remote add origin https://github.com/xxxx/xxxx.git

添加后,远程库的名字就是origin,这是Git默认的叫法,可以改成别的,但一般不建议。

  • 把本地所有内容推到远程库上
$ git push -u origin master

用git push命令,实际上是把当前分支master推送到远程。
加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令(以后只需要git pull就可以拉取)。

  • 以后只需要通过命令就可以提交最新修改到Github
$ git push origin master

4.2删除远程库

  • 使用git remote -v可以查看远程库信息
  • 使用git remote rm 命令可以删除远程库,如
$ git remote rm origin

这里的“删除”是指解除了本地和远程的绑定关系,并不是物理上删除了远程库。要真正删除远程库,需要登陆GIthub,在后台页面选择删除。

4.3从远程库克隆

现在考虑先创建远程库,再从远程库克隆的情形。

  • 创建远程库-在github上新建一个名为gitskills的仓库,并勾选Initialize this repository with a README
  • 使用git clone命令克隆本地库
$ git clone git@github.com:Nkehougaosuni/gitskills.git

GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。

5.分支管理

5.1创建与合并分支

  • 创建dev分支,并切换到dev分支
$ git switch -c dev
# 参数`-c`表示创建并切换,相当于下面两条命令
$ git branch dev
$ git switch dev
  • 使用git branch命令查看当前分支
$ git branch
* dev
  master

git branch命令会列出所有分支,当前分支前会标一个*

  • 使用git merge dev命令将dev分支的工作成果合并到当前分支(master分支)上
$ git merge dev # 将dev分支合并到当前分支(master分支)上
Updating 150ffb8..2e9a1a2
Fast-forward
 k.txt      | 0
 readme.txt | 3 ++-
 2 files changed, 2 insertions(+), 1 deletion(-)
 delete mode 100644 k.txt

git merge命令用于合并指定分支到当前分支
Fast-forward信息表示这次合并是“快进模式”,即直接把master指向dev的当前提交。
事实上还有别的合并方式

  • 使用git branch -d dev命令删除dev分支
$ git branch -d dev
Deleted branch dev (was 2e9a1a2).

不能删除当前所处的分支
Git鼓励使用分支完成某个任务,合并后再删掉分支。
在一个分支有工作尚未add或者commit,此时切换到其他分支,会出现问题。详情可以参考https://blog.csdn.net/w522301629/article/details/81331273

5.2解决冲突

合并分支可能会存在冲突。假如在新建的feature1分支上对readme.txt文件进行修改并提交。并切换到master分支上对readme.txt文件进行修改并提交
在这里插入图片描述

这种情况下,git无法执行快速合并,只能试图把各自的修改合并起来,但这种合并可能有冲突。

$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

使用git status可以告诉我们冲突的文件,然后必须手动解决冲突之后再提交。
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容
解决冲突并提交后的结果如下图。
使用git log --graph --pretty=oneline --abbrev-commit也可以看到分支的合并情况。
在这里插入图片描述
最后删除feature1分支

5.3分支管理策略

合并分支的时候,git会尽可能使用fast forward模式,这种模式下,删除分支后,会丢掉分支信息。
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出曾做过合并,而fast forward合并则看不出来曾做过合并。

$ git merge --no-ff -m "merge with no-ff" dev # 在master分支下对dev分支进行普通合并

因为普通合并会创建一个新的commit,所以要加上-m参数,将commit的描述写进去。
此时通过git log --graph --pretty=oneline --abbrev-commit命令就可以查看分支历史

$ git log --graph --pretty=oneline --abbrev-commit

在这里插入图片描述在这里插入图片描述

分支策略

master分支应该是非常稳定的,仅用来发布新版本,平时不能在上面干活。
dev分支是不稳定的。每个人都应该有自己的分支,并时不时往dev分支上合并。

在这里插入图片描述

5.4Bug分支

当在dev分支上工作,但工作还没有commit时(工作只进行到一半,无法提交),此时在master分支上忽然有一个必须要修复的bug。这时候,可以使用git stash命令将工作现场保存起来。

$ git stash -u

git stash -u可以将包括工作区新增的文件也保存起来。详细可以参考:https://blog.csdn.net/lamp_yang_3533/article/details/80370380
对于切换分支开发,一般使用stash命令,不太建议用commit,如果用commit,会导致很多无效的提交,到时候追溯会比较麻烦

然后就可以放心在需要修改bug的分支上(如master分支)创建临时分支(如issue-101)来修改bug

$ git switch master
$ git switch -c issue-101

修改完bug后,提交,并切换到master分支完成对issue-101分支的合并。

# 修改readme.txt文件
$ git add readme.txt
$ git commit -m "fix bug 101“
[issue-101 e05ecd5] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch master
$ git merge --no-ff -m "mergerd bug fix 101" issue-101
$ git branch -d issue-101 # 删除issue-101

记住修改bug提交的commit-id号,后面复制这次提交需要用到。

然后重新回到dev分支,使用git stash pop命令或者git stash apply命令恢复工作现场。

$ git switch dev 
$ git stash pop

使用cherry-pick命令复制提交到当前分支

dev分支是早期从master分支上分出来的,所以这个bug其实在dev分支上也存在。
可以使用cherry-pick命令修复同样的bug

$ git branch
$ git cherry-pick e05ecd5 # 复制一个特定的提交到当前分支 

cherry pick命令可以让我们能复制一个或多个特定的提交到当前分支
使用git cherry-pick前要保证工作区和暂存区是干净的,所以建议先使用stash命令,再使用git cherry-pick命令。
关于git cherry-pick的用法可以参考详解 git cherry-pick用法

5.5Feature分支

  • 新增一个功能时,最好新建一个feature分支,在上面开发,完成后,再合并,最后删除该分支。
  • 要丢弃一个没有被合并过的分支,可以通过git branch -D <分支名>来强行删除

5.6多人协作

  • 从远程仓库克隆时,实际上默认Git是把本地的master分支和远程的master分支对应起来,并且,远程仓库的默认名称是origin
  • 使用git remote -v命令可以查看远程库信息。
$ git remote -v
origin  https://github.com/Nkehougaosuni/learngit.git (fetch)
origin  https://github.com/Nkehougaosuni/learngit.git (push)

显示了可以抓取和推送的origin地址,如果没有推送权限,就看不到push地址

推送分支

  • 推送分支,就是把改分支上的所有本地提交推送到远程库。推送时,要指定本地分支。
  • 使用git push origin master命令将本地的master分支推送到远程库。
$ git push origin master # 推送master分支到远程库
$ git push origin dev # 推送dev分支到远程库

并非所有本地分支都一定要往远程推送
master分支是主分支,要时刻与远程同步
dev分支是开发分支,团队所有成员都需要在上面工作,所以需要和远程同步
bug分支只用于本地修改bug,没必要推到远程
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发

抓取分支

  • 在另一台电脑(配置SSHkey并添加到Github)或同一台电脑的另一个目录下克隆远程库
$ git clone ...

此时只能看到master分支,但是是可以通过switch命令切换过去到其他分支的,具体有哪些分支存在可以通过branch -r命令查看

  • 使用git switch dev切换到dev分支
$ git switch dev
Switched to a new branch 'dev'
branch 'dev' set up to track 'origin/dev'.

这个命令会自动将dev分支关联(跟踪到)到远程库的dev分支

  • 使用git pull origin <远程分支名>能将远程的分支合并到当前分支
$ git pull origin dev

如果当前分支和远程分支已经建立起了跟踪链接,则可以简写为git pull

多人协作的工作模式

  1. 使用git push origin <分支名>推送自己的修改
  2. 如果推送失败,则因为远程分支比你的本地更新,需要先使用git pull试图合并
  3. 如果合并有冲突,则解决冲突,并在本地提交
  4. 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
    如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>

5.7Rebase

  • 本来两次提交是在master主线上的
    在这里插入图片描述
  • 但因为别人在我们前面推送了远程分支,所以我们无法直接push,需要先git pull,而pull的时候又产生了冲突。
  • 修改完冲突并再次提交时,使用git log可以看到多了两次提交,一次是冲突合并的提交(在一条新的分叉上),一次是修改完冲突的提交

这是因为pull实际上是git fetch+git merge,而merge如果产生冲突,会在一个分叉上生成一个冲突合并的提交,然后需要手动解决冲突并在当前分支产生一个提交。
在这里插入图片描述

  • 而使用git pull -r则实际上是git fetch+git rebase:git先将master指针指向拉取分支,然后根据当前分支有几个提交,就生成rebase的几个阶段。

每个阶段中如果有冲突,都需要解决冲突并提交,然后再使用git rebase --continue命令进入下一个阶段。

在这里插入图片描述

  • 第一阶段有冲突,修改并提交,然后使用git rebase --continue
    在这里插入图片描述
  • 第二阶段有冲突,修改并提交,然后使用git rebase --continue
    在这里插入图片描述
  • 这时,可以发现,使用rebase命令可以把本地分叉的提交历史整理成直线
  • 注意:使用rebase时要特别注意,git的文档特别提示了:只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。因为因为rebase会改变提交历史记录(及commit id等),这会影响到别人使用这一远程仓库。

关于git mergegit rebase的区别可以参考:https://blog.csdn.net/michaelshare/article/details/79108233

6.标签管理

  • 标签是版本库的快照。对应某个commit。

6.1创建标签

  • 使用git tag -a 标签名 -m "说明文字" commit_id可以在当前分支打标签,commit_id不填,则默认打在最新提交的commit

-a指定标签名,可写可不写

  • 使用git tag查看所有已经打上的标签

标签是按照字母顺序排列的

  • 使用git show <标签名>可以查看标签信息。

标签总是和某个commit挂钩,如果某个commit即出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
标签是指向commit的死指针,分支是指向commit的活指针

6.2操作标签

  • 使用git tag -d 标签名可以删除本地标签

创建的标签都只存储在本地,不会自动推送到远程

  • 使用git push origin <标签名>可以将某个本地标签推送到远程
  • 使用git push origin --tages可以一次性推送全部尚未推送到远程的本地标签
  • 使用git push origin :refs/tags/标签名可以删除远程的标签

7.使用Github

  • 在GitHub上,可以任意Fork开源仓库;
  • 自己拥有Fork后的仓库的读写权限;
  • 可以推送pull request给官方仓库来贡献代码。

使用Gitee

自定义Git

忽略特殊文件

  • 忽略某些文件时,需要编写.gitignore文件
  • 忽略文件的原则是:
    忽略操作系统自动生成的文件,比如缩略图等;
    忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
    忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

各种软件的gitignore文件可以参考:https://github.com/github/gitignore

  • 使用git add -f 文件名可以突破.gitignore的限制强行提交
  • .gitignore文件中要排除指定文件的语法是:! 文件名

配置别名

  • 使用git config --global alias.st status就可以用git st代替git status命令
  • 将lg配置成如下:
$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

配置文件

  • 参数–global是针对当前用户起作用,不加则只对当前仓库起作用
  • 当前仓库的Git配置文件在.git/config文件中
  • 当前用户的Git配置文件在用户主目录的隐藏文件.gitconfig
$ cat ~/.gitconfig
[filter "lfs"]
        required = true
        clean = git-lfs clean -- %f
        smudge = git-lfs smudge -- %f
        process = git-lfs filter-process
[user]
        name = Nkehougaosuni
        email = 124226697+Nkehougaosuni@users.noreply.github.com
[alias]
        st = status
        lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

搭建Git服务器

  • 搭建Git服务器需要准备一台Linux机器
  • 第一步:安装git:
$ sudo apt-get install git
  • 第二步:创建一个git用户,用来运行git服务:
$ sudo adduser git
  • 第三步:创建证书登录:
    收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个
  • 第四步:初始化Git仓库:
    先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
$ sudo git init --bare sample.git

Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:

$ sudo chown -R git:git sample.git
  • 第五步:禁用shell登录:
    出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行
$ git:x:1001:1001:,,,:/home/git:/bin/bash

改为:

$ git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

  • 第六步:克隆远程仓库:
    现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@server:/srv/sample.git

使用SourceTree(可视化git界面)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值