Git学习&踩坑记录

Git学习&踩坑记录

LuluyLand

官方用户手册https://git-scm.com/docs/user-manual

准备知识

工作区和暂存区

git版本库包含暂存区(stage或index),add从工作区到index,commit从index到分支master

准备工作

查看帮助

1
$ man git-log
1
$ git help log

进行任何操作前

1
2
$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com

查看远程库的url

1
$ git config --get remote.origin.url #不一定是origin:远程库简写具体情况分析

本地库和远程库

创建版本库(本地库)

  1. 选择一个合适的地方创建一个空目录myprogram

    image-20230821142024612

  2. 在git-bash界面打开该目录并使用初始化为可管理仓库

    1
    2
    3
    4
    5
    shade@LAPTOP-UUSGVNLB MINGW64 d/shade/WYrepo/myprogram/myprogram
    $ git init
    Initialized empty Git repository in ...

    shade@LAPTOP-UUSGVNLB MINGW64 d/shade/WYrepo/myprogram/myprogram(main)

    此时仓库建好了,myprogram目录下有.git目录

    image-20230821142558290

添加远程库

在本地已经创建一个Git仓库,希望在GitHub或Gitee创建一个远程库使两个仓库远程同步

  • 在GitHub上新建一个仓库learngit(仓库 名建议与本地库名同,其它选项默认)

  • 在本地的learngit仓库下运行命令,使本地库与远程库关联

    1
    $ git remote add origin git@github.com:Luluy233/learngit.git

    添加后,远程库的名字就是origin(默认),也可改为其它名字

  • 把本地库的所有内容推送到远程库上:

    1
    2
    3
    $ git push -u origin main #第一次
    $ git push origin main
    $ git push <远程库简称> <远程库分支名>

    注意:push的是已经commit的内容(若当前没有任何commit会报错)

    可以再GitHub网站上看到对应内容

    image-20230821141057710

远程库克隆

远程库:GitHub或Gitee上的仓库

本地库:本地的git仓库

从零开发,选择现在GitHub或Gitee上创建远程库,然后从远程库克隆到本地

  • 登录GitHub,创建新的仓库(选择initialize with a README
  • 用命令git clone克隆一个本地库(在本地库希望的文件夹下克隆)

如希望在WYrepo下建立仓库gitskills,则不用自行新建gitskills文件夹

1
2
#d/shade/Wyrepo
git clone git@github.com:Luluy233/<远程库名>.git #-ssh

删除远程库

此处删除的实际是本地库与远程库的关联,因此删除前可先查看与本地库关联的远程库信息;若要真正删除远程库则需登录对应Gitee或GitHub后台直接删除

查看远程库信息

1
$ git remote -v

然后根据名字删除(origin/orgin)

删除远程库关联

1
$ git remote rm origin

删除版本库(本地.git文件夹)

1
$ find .-name ".git" | xargs rm -Rf

则对应文件夹中.git文件夹被删除

基本使用

git init

在本地库project文件夹下初始化git仓库

1
2
$ git init
Initialized empty Git repository in .git/ #git反馈

文件夹下出现.git文件夹

git add

将修改过的指定文件添加到暂存区index

1
$ git add file1 file2

将所有更改过的内容快照暂存到index中

1
$ git add . 

git commit

永久保存内容的index作为项目的一个版本

1
$ git commit -m "版本信息"

将所有修改内容add到index,再commit到分支

1
$ git commit -a #等价于git add . 加上 git commit

(commit规范)

https://zhuanlan.zhihu.com/p/90281637

https://zhuanlan.zhihu.com/p/182553920

https://www.conventionalcommits.org/zh-hans/v1.0.0-beta.4/

git diff

查看在工作区做出修改但未git add到暂存区index的内容

1
$ git diff

查看即将commit的内容(已经add但未commit

1
$ git diff --cached

git status

查看当前修改过的内容

1
2
3
4
5
6
7
8
$ git status
On branch master
Changes to be committed:
... #修改,已add未commit
Changes not staged for commit:
... #修改,未add
Untracked files:
...

git log

查看commit的信息

1
$ git log

查看每个commit的具体代码修改(每一行)

1
$ git log -p

查看每个commit的修改小节(对哪些文件修改、增添的行数)

1
$  git log --stat --summary

分支管理

git branch

  1. 新建名为dev的分支

    1
    $ git branch dev
  2. 查看现存本地工作区的分支列表

    1
    2
    3
    $ git branch
    dev
    *master #自动创建
  3. 追中远程分支

    1
    $ git branch -u origin/main #在当前分支main下执行

    让本地的main分支追踪远程名为origin仓库的main分支

其中origin需使用如下命令

1
$ git remote add origin <远程仓库URL> #将本地仓库与远程仓库建立连接
  1. 删除分支dev

    必须在其它分支(非dev)下执行删除分支命令

    1
    2
    $ git branch -d dev #某些情况下无法删除
    $ git branch -D dev #强制删除分支

git switch

切换到指定分支dev

1
$ git switch dev

git checkout

可以通过更新工作树的文件使其与索引或指定的树版本相匹配

git checkout <分支名>/<提交哈希值>/<树对象>/<路径参数>

  1. 基本用法

    1
    $ git checkout <branch>

    若本地库不存在<branch>但远程库·<remote>存在同名的<branch>,则会在本地库新建分支<branch>并自动追踪远程分支<remote>/<branch>

    若本地和远程库都不存在分支<branch>,则报错,如下:

    1
    2
    $ git checkout bbb
    error: pathspec 'bbb' did not match any file(s) known to git
  2. 省略分支名

    1
    $ git checkout

    会自动检测当前分支的信息(追踪的远程库等),如果没有追踪的远程库则返回空

    如:

    1
    2
    3
    #当前本地的dev-BuyerCenter
    Your branch is ahead of 'origin/dev-BuyerCenter' by 3 commits.
    (use "git push" to publish your local commits)
  3. 参数-b/-B

    1
    $ git checkout -b|-B <new-branch> [<start-point>]

    若远程库和本地库都不存在,则-b会新建分支<branch>

git merge

master分支和dev分支修改了不同的内容,master分支下运行如下命令,可将dev分支合并到master,如果没有冲突,则合并成功

没有冲突:没有对同一个文件修改

1
$ git merge dev #当前为master分支

发生冲突,会提示需要解决冲突再合并,进入如下界面(main|MERGING)

1
2
3
4
5
6
7
shade@LAPTOP-UUSGVNLB MINGW64 /d/mycreate/gitlearn (main)
$ git merge dev
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

shade@LAPTOP-UUSGVNLB MINGW64 /d/mycreate/gitlearn (main|MERGING)
  1. 可以使用git diff命令显示分支差异

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    shade@LAPTOP-UUSGVNLB MINGW64 /d/mycreate/gitlearn (main|MERGING)
    $ git diff
    diff --cc file1.txt
    index b0e228e,0112b68..0000000
    --- a/file1.txt
    +++ b/file1.txt
    @@@ -1,3 -1,2 +1,7 @@@
    this is file1
    -hello,dev,is conflict
    ++<<<<<<< HEAD
    +modified by branch-dev
    - hello, this is master
    ++hello, this is master
    ++=======
    ++hello,dev,is conflict
    ++>>>>>>> dev

    打开冲突文件夹会显示@@@ -1,3 -1,2 +1,7 @@@下的内容

    <<<<<<< HEAD=======之间是当前分支main的修改,而=======>>>>>>> dev之间是分支dev的修改,此时需要手动编辑这部分代码。

  2. 手动编辑解决冲突后,可以使用git add+git commit来讲结果合并到merge的结果

  3. 使用gitk图形化显示合并结果

git mv

若文件夹发生重命名,则使用如下命令进行移动

1
$ git mv <old-location> <new-location>

gitk

图形化显示各个分支merge的结果:

1
$ gitk

结果如下:

image-20230820212250846

团队合作

git clone

从远程库克隆到本地

1
$ git clone <远程库的ssh或http> <可选:本地库名称/否则与远程库同名>

git pull

pull = fetch + merge

从远程分支fetch,并merge到本地分支;

1
$ git pull <远程库> master #从<远程库>的master分支pull到当前分支

如果发生冲突,则git仍旧执行fetch但不执行merge,此时本地需要先消除更改,再重新pull

(背景:Alice要pull来自Bob的更改)

如果Bob的工作与Alice的工作发生冲突,那么Alice将使用她的工作树和索引来解决冲突,并且现有的本地更改将干扰冲突解决过程(Git仍然会执行fetch,但会拒绝merge)。

  1. 一种常见方法(poe):

    git stash:将当前本地更改保存到一个临时的存储区域,使工作树和索引树干净,再执行git pull获取远程分支最新更改,并解决冲突,完成冲突解决后,可以使用git stash pop将之前保存的本地更改重新应用到工作树

  2. 另一种方法

    将本地更改提交到当前分支,并在冲突解决后再次进行提交。这种方法要求Alice首先使用git addgit commit命令将本地更改提交到当前分支。然后,执行git pull来获取远程分支的最新更改并进行冲突解决。完成冲突解决后,Alice可以再次使用git addgit commit命令来提交合并后的更改。

  3. pull策略

    https://blog.csdn.net/qq_39248724/article/details/129437956

    • 查看当前git的pull策略:

      1
      git config --get pull.rebase

      返回值可能为:

      • true:表示 pull 使用的是 rebase 策略。

      • false:表示 pull 使用的是 merge 策略(默认值)。

      • 未设置或不存在该配置项:表示使用 Git 的默认行为,即根据 Git 版本和配置文件中的设置决定使用的策略。

      • 配置为rebase策略

        1
        git config --global pull.rebase true

        当你在 Git 中执行 git pull 命令时,它会从远程仓库拉取最新的提交,并尝试将这些提交合并到你的本地分支。默认情况下,Git 使用合并(merge)策略来将远程提交与本地提交合并在一起。

        然而,通过设置 pull.rebasetrue,你告诉 Git 在执行 git pull 时使用 rebase(变基)策略而不是合并策略。

        Rebase 策略将会执行以下操作:

        1. 从远程仓库拉取最新的提交。
        2. 将当前分支上的本地提交按顺序逐个应用在这些最新提交之上。
        3. 如果在应用本地提交的过程中发生冲突,Git 会让你解决冲突,并在解决完冲突后继续应用剩余的本地提交。
        4. 完成后,你的本地分支将指向一个新的提交,其中包含了最新的远程提交和你的本地提交。

git fetch

通过fetch命令,Alice可以在不合并的情况下看到Bob做了什么;

(安全:即使Alice本地修改未commit)

这允许Alice检查Bob做了什么,使用一个特殊的符号FETCH_HEAD,以确定他是否有值得提取的东西,如下:

1
alice$ git fetch /home/bob/myrepo master

下面的命令显示在Bob的分支中但不在Alice的分支中的内容

1
alice$ git log -p HEAD..FETCH_HEAD

还可以使用如下命令查看Bob在分叉后做了什么(两个点)

1
$ gitk HEAD..FETCH_HEAD #远程库的内容

使用如下命令查看两人在分支后都做了什么(三个点)

1
$ gitk HEAD...FETCH_HEAD

在一个小而紧密的团队中工作时,经常与同一个仓库进行交互是很常见的。通过定义远程仓库的简写,可以使这一过程更加简便:

1
alice$ git remote add bob /home/bob/myrepo

通过这样的设置,Alice可以使用 git fetch 命令单独执行拉取操作的第一部分,而不将其与自己的分支合并,使用以下命令:

1
alice$ git fetch bob

这样,Alice 就可以从 Bob 的仓库中获取最新的更改,但不会自动合并到她自己的分支中。通过这种方式,Alice 可以获取 Bob 的更新,然后根据需要进一步处理。

Alice使用如下命令显示Bob所做的一切修改(与Alice的master区别)

1
alice$ git log -p master..bob/master

接着Alice可以将这些修改合并到自己的分支

1
alice$ git merge bob/master

上述的merge操作等同于如下:

1
>alice$ git pull . remotes/bob/master #合并到当前分支

接着Bob可以更新他的分支(与alice修改一致)

1
>bob$ git pull

git remote

用于管理远程库的相关操作(poe)

  1. 查看

    显示当前仓库中配置的所有远程库简写名称

    1
    $ git remote

    显示当前仓库中配置的所有远程库的简写名称及其对应的远程仓库URL

    1
    $ git remote -v
  2. 添加

    添加一个新的远程仓库,指定简写名称和对应的仓库URL

    1
    $ git remote add <name> <url>

    $ git remote add bob /home/bob/myrepo

  3. 重命名

    重命名一个已存在的远程库简写

    1
    $ git remote rename <old-name> <new-name>
  4. 删除

    删除已存在远程仓库简写

    1
    2
    $ git remote remove <name>
    $ git remote rm <name>

提交历史

git log其它用法

1
2
3
4
$ git log v2.5..v2.6            # commits between v2.5 and v2.6
$ git log v2.5.. # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile # commits since v2.5 which modify Makefile
1
2
$ git log master..stable #在分支stable提交但是不在分支master提交
$ git log stable..master #在分支master提交但是不在分支stable提交

git show

查看具体某个版本修改的内容(具体修改)

版本号不一定要完整的,只要可识别(可前几位)

1
2
3
$ git show <对应版本号/哈希值>
$ git show HEAD #当前分支的第一个版本
$ git show dev #dev分支的第一个版本

可以查看当前分支的父母级别

1
2
3
$ git show HEAD^
$ git show HEAD^^
$ git show HEAD~4
1
2
$ git show HEAD^1 #等同HEAD^
$ git show HEAD^2 #等同HEAD^^

git tag

给分支版本号标签名

1
$ git tag <标签名> <版本号>

git reset

版本回溯,回溯到指定版本号

1
$ git reset --hard <版本号/HEAD相关>
1
$ git reset --hard HEAD^

git revert

撤销提交:创建新的提交来撤销之前的提交

1
$ git revert <版本号>

git grep

在指定版本中搜索代码中的关键词,若不指定版本号则默认在当前版本下搜索

1
$ git grep "关键词" <版本号/标签名>

对象数据库object database

对象数据库类型

https://eagain.net/articles/git-for-computer-scientists/

git对象存储一个对象的DAG,由SHA-1哈希标识;

数据类型包括blobtreecommittag

blob

文件内容,最简单(一堆字节)

tree

目录结构,(引用blob、其它tree子目录)

image-20230821083955725

在DAG中指向其它结点的任一结点,都要依赖于另一个结点;否则可以用命令**git gc** 收集垃圾;如果文件系统中有很多个结点都没有指向他们的(parent),则可以用 git fsck --lost-found 命令来回收

commit

提交对象。commit引用tree,被其它n多个commit引用(它的parent)

若commit没有parent,则是init commit;

若commit有多个直接parent,则是merge的结果;

git commit会添加1个commit结点到DAG中,并将对应refs便利贴移动到该结点

refs(黄色):heads或branches,向DAG结点上的便利贴

remote refs(蓝色):远程分支

image-20230821085629627

tag

标签对象:既是DAG结点也是post-it note(便利贴),指向一个commit

cat-file

获取git对象的类型:

1
$ git cat-file -t <哈希值>

显示与哈希值对应的提交对象具体信息

1
2
3
4
5
$ git cat-file commit <哈希值>
tree .....
parent .... #上一提交
author .... #作者
committer ... #提交者:一般同上

显示blob对应的信息

1
2
$ git cat-file blob 3b18e512
hello world

ls-tree

查看git的文件和目录结构以及与各个版本之间的关系;

输出:文件模式(权限、类型)、类型、对象哈希、文件路径

文件模式100644、文件类型(blob 3b18e512)、路径名(file.txt)

1
2
$ git ls-tree <哈希值>
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad file.txt

find .git/…

查看SHA-1名称存储的git目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ find .git/objects/
.git/objects/
.git/objects/3b
.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
.git/objects/92
.git/objects/92/b8b694ffb1675e5975148e1121810081dbdffe
.git/objects/99
.git/objects/99/84a6e4efb078f2866cc3df35b0f4a42c661684
.git/objects/a0
.git/objects/a0/423896973644771497bdc03eb99d5281615b51
.git/objects/d0
.git/objects/d0/492b368b66bdabf2ac1fd8c92b39d3db916e59
.git/objects/d0/eb06c65cff138564ab9195e46a2f49330f25eb
.git/objects/info
.git/objects/pack

cat .git/…

显示当前所在分支:main

1
2
$ cat .git/HEAD
ref: refs/heads/main

显示

索引文件index

git add:存储一个新的blob,将对其的引用放入索引文件中。

git clone

从远程库remotes/MYSERVER/master克隆到本地

image-20230821090017272

git fetch

从远程库拉取(fetch)新提交,但是还没合并(merge)

此时本地master指向a,远程master指向b

image-20230821090144176

git merge

执行命令git merge remotes/MYSERVER/master

  1. 若本地没有领先远程的新提交,则本地便利贴master指向b,

    image-20230821090338017

  2. 若远程新提交c、若本地新提交d,git merge前结构如下

    image-20230821090622172

    git merge后结构如下:

    新建结点e合并结点c和d,本地master指向e

    image-20230821090653097

实践问题

2023.08.21

合并远程分支和本地分支

本地dev-BuyerCenter有新提交,远程dev也有新提交,要合并远程和本地

  1. git fetch

  2. git merge,显示如下,此时进入(BuyerCenter | MERGING)

    image-20230821094612584

    • CONFLICT(content):对同一文件修改,则点开提示的文件src/router/index.js查看本地和远程的区别并修改
    • CONFLICT(file location):远程对目录进行重命名,此时不需要进行任何修改(默认用远程的)
  3. 解决冲突后git add + git commit提交合并即可

2023.8.24

git push之前忘记先git fetch了会怎么样吗

操作:先git push,push完了发现忘记fetch了,再fetch,然后信息如下

1
2
3
4
5
6
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Total 6 (delta 5), reused 6 (delta 5), pack-reused 0
Unpacking objects: 100% (6/6), 760 bytes | 50.00 KiB/s, done.
From github.com:DBTeam2023/GorgeousHuaShang-frontend
7cc6aaa..a77ad2a dev-order -> origin/dev-order

无大事发生

2023.12.26

本地已做了修改,又想从远程拉取代码,报错

1
2
3
4
$ git pull
error: cannot pull with rebase: You have unstaged changes.
error: additionally, your index contains uncommitted changes.
error: please commit or stash them.

先暂时丢弃本地操作,pull后再恢复

1
2
3
4
#逐步执行下述命令
git stash
git pull
git stash apply

2025.4.20

在执行git push时报错为:

1
2
3
4
remote: error: Trace: ef2fe96bd712c1155b8f7d643d9376c04ad805e4973277460183326d89650b07
remote: error: See https://gh.io/lfs for more information.
remote: error: File test/data/cifar/cifar-10-python.tar.gz is 162.60 MB; this exceeds GitHub's file size limit of 100.00 MB
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.

考虑到原因是上传文件超出容量限制,并且是数据集文件,因此修改.gitigore忽略test/data/文件夹,保存.gitignore文件后,因为之前已将该文件夹添加到版本控制中,需要先将其从暂存区移除,使用如下命令

1
git rm -r --cached test/data/

然后提交修改

1
git commit -m "fix: 忽略test/data/文件夹"

test/data/文件夹就会被git忽略,不再参与版本控制

  • 标题: Git学习&踩坑记录
  • 作者: LuluyLand
  • 创建于 : 2025-04-14 19:23:45
  • 更新于 : 2025-04-20 23:49:03
  • 链接: https://luluy233.github.io/2025/04/14/GitLearn/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论