【Git 入门】动手学习 Git

参考教程:Git教程 - 廖雪峰的官方网站

没有具体学习 10 使用 Gitee11.3 搭建 Git服务器12 使用 Source Tree

1 安装

参考教程:Git 详细安装教程(详解 Git 安装过程的每一个步骤)

打开 Git Bash,设置个人信息:

1
2
$ git config --global user.name "Xuan-Van"
$ git config --global user.email "wuqi7137@qq.com"

2 创建版本库

  1. 创建空目录 learngit

    1
    2
    3
    4
    5
    $ cd Desktop/Project
    $ mkdir learngit
    $ cd learngit
    $ pwd # 显示当前目录
    /c/Users/21830/Desktop/Project/learngit
  2. learngit 变成 Git 可以管理的仓库:

    1
    2
    $ git init
    Initialized empty Git repository in C:/Users/21830/Desktop/Project/learngit/.git/
  3. 列出目录所有内容:

    1
    2
    $ ls -ah # -a:显示所有文件,-h:以易读的格式显示文件大小
    ./ ../ .git/
  4. learngit 目录下编写一个 readme.txt 文件:

    1
    $ vim readme.txt # 之后按I进入插入模式来编辑,写好后按Esc退出,输入:wq保存文件并退出Vim    

    内容如下:

     Git is a version control system.
     Git is free software.
    
  5. readme.txt 添加并提交到仓库:

    1
    2
    3
    4
    5
    $ git add readme.txt # 可重复使用,添加多个文件
    $ git commit -m "wrote a readme file" # -m: messages(提交说明)
    [master (root-commit) 15ae68d] wrote a readme file
    1 file changed, 2 insertions(+)
    create mode 100644 readme.txt
  6. 删除本地仓库:在对应目录下 rm -rf .git 后删除文件夹即可。

3 时光机穿梭

  1. 用 Vim 修改 readme.txt,内容如下:

     Git is a distributed version control system.
     Git is free software.
    
  2. 查看仓库当前的状态:

    1
    2
    3
    4
    5
    6
    7
    8
    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt

    no changes added to commit (use "git add" and/or "git commit -a")
  3. 查看 readme.txt 的修改内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git diff readme.txt
    diff --git a/readme.txt b/readme.txt
    index 46d49bf..9247db6 100644
    --- a/readme.txt
    +++ b/readme.txt
    @@ -1,2 +1,2 @@
    -Git is a version control system.
    +Git is a distributed version control system.
    Git is free software.
  4. 添加 readme.txt 并查看仓库状态:

    1
    2
    3
    4
    5
    6
    $ git add readme.txt
    $ git status
    On branch master
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    modified: readme.txt
  5. 提交 readme.txt 并查看仓库状态:

    1
    2
    3
    4
    5
    6
    7
    $ git commit -m "add distributed"
    [master daaf95b] add distributed
    1 file changed, 1 insertion(+), 1 deletion(-)

    $ git status
    On branch master
    nothing to commit, working tree clean

3.1 版本回退

  1. 用 Vim 修改 readme.txt,内容如下:

     Git is a distributed version control system.
     Git is free software distributed under the GPL.
    
  2. 提交 readme.txt

    1
    2
    3
    4
    $ git add readme.txt
    $ git commit -m "append GPL"
    [master 97b0ca9] add GPL
    1 file changed, 1 insertion(+), 1 deletion(-)
  3. 查看历史提交日志:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ git log
    commit 97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (HEAD -> master)
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:53:32 2024 +0800

    add GPL

    commit daaf95bc4582d74baf9c4d267f7c6e838aaaa224
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:48:39 2024 +0800

    add distributed

    commit 15ae68d25889731562f9db61de8e45a75505cad3
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:30:57 2024 +0800

    wrote a readme file
  4. 简要查看从最近到最远的提交日志:

    1
    2
    3
    4
    $ git log --pretty=oneline
    97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (HEAD -> master) add GPL
    daaf95bc4582d74baf9c4d267f7c6e838aaaa224 add distributed
    15ae68d25889731562f9db61de8e45a75505cad3 wrote a readme file
  5. 回退到上一个版本:

    1
    2
    $ git reset --hard HEAD^
    HEAD is now at daaf95b add distributed
    • 最新版本是 HEAD,上一个版本是 HEAD^,上上一个版本是 HEAD^^,上 n 个版本写是 HEAD~n
    • --hard 会回退到上个版本的已提交状态,--soft 会回退到上个版本的未提交状态,--mixed 会回退到上个版本已添加但未提交的状态。

    查看 readme.txt 来确认:

    1
    2
    3
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software.

  6. 查看当前版本库的提交日志:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git log
    commit daaf95bc4582d74baf9c4d267f7c6e838aaaa224 (HEAD -> master)
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:48:39 2024 +0800

    add distributed

    commit 15ae68d25889731562f9db61de8e45a75505cad3
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:30:57 2024 +0800

    wrote a readme file
  7. 回到指定版本(add GPL 版本):

    1
    2
    $ git reset --hard 97b0 # 版本号填写前几位
    HEAD is now at 97b0ca9 add GPL

    查看 readme.txt 来确认:

    1
    2
    3
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
  8. 查看历史命令,以便确认未来版本:

    1
    2
    3
    4
    5
    6
    $ git reflog
    97b0ca9 (HEAD -> master) HEAD@{0}: reset: moving to 97b0
    daaf95b HEAD@{1}: reset: moving to HEAD^
    97b0ca9 (HEAD -> master) HEAD@{2}: commit: add GPL
    daaf95b HEAD@{3}: commit: add distributed
    15ae68d HEAD@{4}: commit (initial): wrote a readme file

3.2 工作区和暂存区

  1. 工作区:可见的目录,一个文件夹 learngit;版本库:工作区中的隐藏目录 .git,其中主要有暂存区 stage 、主分支 master 和指向 master 的指针 HEAD
  2. git add 将文件修改添加到暂存区,git commit 将暂存区的所有内容提交到当前分支。
  3. readme.txt 添加一行内容:
    1
    2
    3
    4
    5
    $ echo Git has a mutable index called stage. >> readme.txt
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
  4. 在工作区新增一个 LICENSE 文件,内容与 readme.txt 一致:
    1
    2
    3
    4
    5
    $ cat readme.txt >> LICENSE
    $ cat LICENSE
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
  5. 查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt

    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    LICENSE

    no changes added to commit (use "git add" and/or "git commit -a")
  6. 添加两个文件到暂存区,查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    $ git add readme.txt
    $ git add LICENSE
    $ git status
    On branch master
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    new file: LICENSE
    modified: readme.txt
  7. 提交暂存区的文件,查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    $ git commit -m "understand how stage works"
    [master 26c8682] understand how stage works
    2 files changed, 4 insertions(+)
    create mode 100644 LICENSE

    $ git status
    On branch master
    nothing to commit, working tree clean

3.3 管理修改

  1. readme.txt 添加一行内容:
    1
    2
    3
    4
    5
    6
    $ echo Git tracks changes. >> readme.txt
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes.
  2. 添加到暂存区,查看仓库状态:
    1
    2
    3
    4
    5
    6
    $ git add readme.txt
    $ git status
    On branch master
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    modified: readme.txt
  3. 再次修改 readme.txt
    1
    2
    3
    4
    5
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
  4. 提交暂存区的文件,查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git commit -m "git tracks changes"
    [master a914ff6] git tracks changes
    1 file changed, 1 insertion(+)

    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt

    no changes added to commit (use "git add" and/or "git commit -a")
  5. 查看工作区和版本库里最新版本的区别:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ git diff HEAD -- readme.txt
    diff --git a/readme.txt b/readme.txt
    index 76d770f..a9c5755 100644
    --- a/readme.txt
    +++ b/readme.txt
    @@ -1,4 +1,4 @@
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    -Git tracks changes.
    +Git tracks changes of files.
  6. 添加并提交文件,查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    $ git add readme.txt
    $ git commit -m "git tracks changes of ilfes"
    [master f896b61] git tracks changes of ilfes
    1 file changed, 1 insertion(+), 1 deletion(-)

    $ git status
    On branch master
    nothing to commit, working tree clean

3.4 撤销修改

  1. readme.txt 添加一行内容, 查看仓库状态:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ echo My stupid boss still prefers SVN. >> readme.txt
    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt

    no changes added to commit (use "git add" and/or "git commit -a")
  2. 丢弃工作区的修改,让文件回到最近一次 git commitgit add 时的状态:
    1
    2
    3
    4
    5
    6
    $ git checkout -- readme.txt
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
  3. readme.txt 添加一行内容,并添加到暂存区:
    1
    2
    3
    4
    5
    6
    7
    $ echo My stupid boss still prefers SVN. >> readme.txt
    $ git add readme.txt
    $ git status
    On branch master
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    modified: readme.txt
  4. 撤销暂存区的修改,丢弃工作区的修改:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ git reset HEAD readme.txt
    Unstaged changes after reset:
    M readme.txt

    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt

    no changes added to commit (use "git add" and/or "git commit -a")

    $ git checkout -- readme.txt
    $ git status
    On branch master
    nothing to commit, working tree clean
  5. 如果错误的内容提交到了版本库,可以回退到上一个版本。

3.5 删除文件

  1. 添加一个 test.txt 到 Git 并提交:
    1
    2
    3
    4
    5
    6
    $ echo Hello World! >> test.txt
    $ git add test.txt
    $ git commit -m "add test.txt"
    [master e309196] add test.txt
    1 file changed, 1 insertion(+)
    create mode 100644 test.txt
  2. 删除 test.txt
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ rm test.txt
    $ git status
    On branch master
    Changes not staged for commit:
    (use "git add/rm <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    deleted: test.txt

    no changes added to commit (use "git add" and/or "git commit -a")
  3. 从版本库中删除并提交,这时 git rmgit add 的效果是一样的:
    1
    2
    3
    4
    5
    6
    7
    $ git rm test.txt
    rm 'test.txt'

    $ git commit -m "remove test.txt"
    [master 49a82cf] remove test.txt
    1 file changed, 1 deletion(-)
    delete mode 100644 test.txt
  4. 如果手动误删,可以用 git checkout -- test.txt 把误删的文件恢复到最新版本,但是会丢失最近一次提交后你修改的内容。从来没有被添加到版本库就被删除的文件,是无法恢复的

4 远程仓库

  1. 创建 SSH Key:
    1
    $ ssh-keygen -t rsa -C "wuqi7137@qq.com"
    然后一路回车,接着到用户主目录中找到 .ssh 目录,里面有 id_rsa(私钥,禁止泄露)和 id_rsa.pub(公钥)两个文件。
  2. 添加 SSH Key:
    graph LR
        A[登录 GitHub] --> B[Settings]
        B --> C[SSH and GPG keys]
        C --> D[New SSH key]
        D --> E["Title填写“SSH Key”<br>Key粘贴id_rsa.pub中的内容"]
        E --> F[Add SSH key]
    
  3. 验证 SSH 成功连接:
    1
    2
    $ ssh -T git@github.com
    Hi Xuan-Van! You've successfully authenticated, but GitHub does not provide shell access.

4.1 添加远程库

  1. 在 GitHub 上新建一个 Repository,名称为 learngit,并与本地 learngit进行关联,origin 是默认习惯命名:

    1
    $ git remote add origin git@github.com:Xuan-Van/learngit.git

    报错:fatal: not a git repository (or any of the parent directories): .git
    原因:文件路径不对,应该到 learngit 目录中执行。
    还可以使用 HTTPS 协议进行连接,将 git@github.com:Xuan-Van/learngit.git 替换为 https://github.com/Xuan-Van/learngit即可。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ git push -u origin master
    Enumerating objects: 22, done.
    Counting objects: 100% (22/22), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (18/18), done.
    Writing objects: 100% (22/22), 1.82 KiB | 622.00 KiB/s, done.
    Total 22 (delta 6), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (6/6), done.
    To github.com:Xuan-Van/learngit.git
    * [new branch] master -> master
    branch 'master' set up to track 'origin/master'.
    • git push -u origin master 是第一次推送时使用的,不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来。

      报错:
      To github.com:Xuan-Van/learngit.git
      ! [rejected] master -> master (fetch first)
      error: failed to push some refs to ‘github.com:Xuan-Van/learngit.git’
      hint: Updates were rejected because the remote contains work that you do not
      hint: have locally. This is usually caused by another repository pushing to
      hint: the same ref. If you want to integrate the remote changes, use
      hint: ‘git pull’ before pushing again.
      hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.
      原因:在尝试推送更改到远程仓库时,远程仓库已经包含了本地没有的更改。

    • git push origin master 把本地 master 分支的最新修改推送至 GitHub。
  3. 查看远程库信息:

    1
    2
    3
    $ git remote -v
    origin git@github.com:Xuan-Van/learngit.git (fetch)
    origin git@github.com:Xuan-Van/learngit.git (push)
  4. 使用 git remote rm origin 来解除本地和远程的绑定关系。

4.2 从远程库克隆

  1. 在 GitHub 上新建一个 Repository,名称为 gitskills,勾选 Add a README file,GitHub 自动创建一个 README.md 文件。
  2. 克隆一个本地库:
    1
    2
    3
    4
    5
    6
    $ git clone git@github.com:Xuan-Van/gitskills.git
    Cloning into 'gitskills'...
    remote: Enumerating objects: 3, done.
    remote: Counting objects: 100% (3/3), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    Receiving objects: 100% (3/3), done.
    可以使用 git clone GitHub的Repository网址 来克隆自己或他人的远程库。
  3. 克隆成功:
    1
    2
    3
    $ cd gitskills/
    $ ls
    README.md

4.3 使用 GitHub

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

5 分支管理

5.1 创建与合并分支

  1. 创建 dev 分支并切换到 dev 分支:

    1
    2
    $ git checkout -b dev
    Switched to a new branch 'dev'

    该命令相当于:

    1
    2
    3
    $ git branch dev # 创建
    $ git checkout dev # 切换
    Switched to branch 'dev'
  2. git branch 命令查看当前分支 *

    1
    2
    3
    $ git branch
    * dev
    master
  3. 修改 readme.txt,并提交:

    1
    2
    3
    4
    5
    $ echo Creating a new branch is quick. >> readme.txt
    $ git add readme.txt
    $ git commit -m "branch test"
    [dev cbcac43] branch test
    1 file changed, 1 insertion(+)
  4. 切换回 master 分支,查看 readme.txt 文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git checkout master
    Switched to branch 'master'
    Your branch is up to date with 'origin/master'.

    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
  5. dev 分支的工作成果合并到 master 分支上,,查看 readme.txt 文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git merge dev # 合并指定分支到当前分支
    Updating 49a82cf..cbcac43
    Fast-forward # 快件模式,直接把 master 指向 dev 的当前提交
    readme.txt | 1 +
    1 file changed, 1 insertion(+)

    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
    Creating a new branch is quick.
  6. 删除 dev 分支,查看分支:

    1
    2
    3
    4
    5
    $ git branch -d dev
    Deleted branch dev (was cbcac43).

    $ git branch
    * master
  7. switch 命令:

    • 创建并切换到新的 dev 分支:
      1
      2
      $ git switch -c dev
      Switched to a new branch 'dev'
    • 直接切换到已有的 master 分支:
      1
      2
      $ git switch master
      Switched to branch 'master'

5.2 解决冲突

  1. 准备新的 feature1 分支:

    1
    2
    $ git switch -c feature1
    Switched to a new branch 'feature1'
  2. 修改 readme.txt 最后一行,改为:

     Creating a new branch is quick AND simple.
    
  3. feature1 分支上提交:

    1
    2
    3
    4
    $ git add readme.txt
    $ git commit -m "AND simple"
    [feature1 3bc9c41] AND simple
    1 file changed, 1 insertion(+), 1 deletion(-)
  4. 切换到 master 分支:

    1
    2
    3
    4
    $ git switch master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)
  5. master 分支上把 readme.txt 文件的最后一行改为:

     Creating a new branch is quick & simple.
    
  6. 提交:

    1
    2
    3
    4
    $ git add readme.txt
    $ git commit -m "& simple"
    [master 4d30980] & simple
    1 file changed, 1 insertion(+), 1 deletion(-)
  7. 合并冲突:

    1
    2
    3
    4
    $ git merge feature1
    Auto-merging readme.txt
    CONFLICT (content): Merge conflict in readme.txt
    Automatic merge failed; fix conflicts and then commit the result.
  8. 查看仓库状态:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 2 commits.
    (use "git push" to publish your local commits)

    You have unmerged paths.
    (fix conflicts and run "git commit")
    (use "git merge --abort" to abort the merge)

    Unmerged paths:
    (use "git add <file>..." to mark resolution)
    both modified: readme.txt

    no changes added to commit (use "git add" and/or "git commit -a")
  9. 查看 readme.txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ cat readme.txt
    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
    <<<<<<< HEAD
    Creating a new branch is quick & simple.
    =======
    Creating a new branch is quick AND simple.
    >>>>>>> feature1
  10. 修改如下后保存:

    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
    Creating a new branch is quick and simple.
    
  11. 再提交:

    1
    2
    3
    $ git add readme.txt
    $ git commit -m "conflict fixed"
    [master 1b8779e] conflict fixed
  12. 用带参数的 git log 也可以看到分支的合并情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ git log --graph --pretty=oneline --abbrev-commit
    * 1b8779e (HEAD -> master) conflict fixed
    |\
    | * 3bc9c41 (feature1) AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf (origin/master) remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file
  13. 删除 feature1 分支:

    1
    2
    $ git branch -d feature1
    Deleted branch feature1 (was 3bc9c41).

5.3 分支管理策略

  1. 创建并切换 dev 分支:

    1
    2
    $ git switch -c dev
    Switched to a new branch 'dev'
  2. 修改 readme.txt 文件,并提交一个新的 commit

    1
    2
    3
    4
    $ git add readme.txt
    $ git commit -m "add merge"
    [dev 8cca272] add merge
    1 file changed, 1 insertion(+)
  3. 切换回 master

    1
    2
    $ git switch master
    Switched to branch 'master'
  4. 准备合并 dev 分支,--no-ff 表示禁用 Fast forward,可以看出合并历史:

    1
    2
    3
    4
    $ git merge --no-ff -m "merge with no-ff" dev
    Merge made by the 'ort' strategy.
    readme.txt | 1 +
    1 file changed, 1 insertion(+)
  5. git log 查看分支历史:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ git log --graph --pretty=oneline --abbrev-commit
    * 98f7914 (HEAD -> master) merge with no-ff
    |\
    | * 8cca272 (dev) add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf (origin/master) remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file
  6. master 分支是非常稳定的,仅用来发布新版本;dev 分支是不稳定的,用来日常开发。团队成员在 dev 分支上创建自己的分支,往 dev 分支上合并。

5.4 Bug 分支

  1. 当前 dev 上的任务还未提交:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ git status
    On branch dev
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    new file: hello.py

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: readme.txt
  2. git stash 把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
    1
    2
    3
    4
    5
    6
    $ git stash
    Saved working directory and index state WIP on dev: 8cca272 add merge

    $ git status
    On branch dev
    nothing to commit, working tree clean
  3. master 分支上修复 bug,就从 master 创建临时分支:
    1
    2
    3
    4
    5
    6
    7
    $ git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
    (use "git push" to publish your local commits)

    $ git checkout -b issue-101
    Switched to a new branch 'issue-101'
  4. 修复 bug,把“Git is free software …”改为“Git is a free software …”,然后提交:
    1
    2
    3
    4
    $ git add readme.txt
    $ git commit -m "fix bug 101"
    [issue-101 092f44e] fix bug 101
    1 file changed, 1 insertion(+), 1 deletion(-)
  5. 修复完成后,切换到 master 分支,并完成合并,最后删除 issue-101 分支:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git switch master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
    (use "git push" to publish your local commits)

    $ git merge --no-ff -m "merged bug fix 101" issue-101
    Merge made by the 'ort' strategy.
    readme.txt | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    $ git branch -d issue-101
    Deleted branch issue-101 (was 092f44e).
  6. 回到 dev 分支工作:
    1
    2
    3
    4
    5
    6
    $ git switch dev
    Switched to branch 'dev'

    $ git status
    On branch dev
    nothing to commit, working tree clean
  7. 查看工作现场:
    1
    2
    $ git stash list
    stash@{0}: WIP on dev: 8cca272 add merge
  8. 恢复工作现场:
    • git stash apply:恢复后,stash 内容并不删除,需要用 git stash drop 来删除;
    • git stash pop,恢复的同时把 stash 内容也删了:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      $ git stash pop
      On branch dev
      Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
      new file: hello.py

      Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
      modified: readme.txt

      Dropped refs/stash@{0} (303e10edcbd261d38e8ebffb64db91d3914b2e9e)
  9. 再用 git stash list 查看,就看不到任何 stash 内容了。可以多次 stash,恢复的时候先用 git stash list 查看,然后用命令 git stash apply stash@{0} 恢复指定的 stash
  10. dev 分支上修复同样的 bug:
    1
    2
    3
    4
    $ git cherry-pick 092f44e # fix bug 101 的commit号
    [dev 9ed458e] fix bug 101
    Date: Sun Nov 10 15:19:44 2024 +0800
    1 file changed, 1 insertion(+), 1 deletion(-)

5.5 Feature 分支

  1. 每添加一个新功能,最好新建一个 feature 分支:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ git switch -c feature-vulcan
    Switched to a new branch 'feature-vulcan'

    $ vim vulcan.py
    $ git add vulcan.py
    $ git status
    On branch feature-vulcan
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    new file: vulcan.py

    $ git commit -m "add feature vulcan"
    [feature-vulcan 3372ec0] add feature vulcan
    1 file changed, 1 insertion(+)
    create mode 100644 vulcan.py
  2. 切回 dev,取消新功能:
    1
    2
    3
    4
    5
    6
    7
    $ git switch dev
    Switched to branch 'dev'

    $ git branch -d feature-vulcan
    error: the branch 'feature-vulcan' is not fully merged
    hint: If you are sure you want to delete it, run 'git branch -D feature-vulcan'
    hint: Disable this message with "git config advice.forceDeleteBranch false"
  3. 删除失败,feature-vulcan 分支还没有被合并,如果删除,将丢失掉修改。如果要强行删除,需要使用大写的 -D 参数:
    1
    2
    $ git branch -D feature-vulcan
    Deleted branch feature-vulcan (was 3372ec0).

5.6 多人协作

  1. 查看远程库的信息:
    1
    2
    $ git remote
    origin # 远程仓库的默认名称
  2. 显示更详细的信息:
    1
    2
    3
    $ git remote -v
    origin git@github.com:Xuan-Van/learngit.git (fetch)
    origin git@github.com:Xuan-Van/learngit.git (push)
  3. 推送分支,把该分支上的所有本地提交推送到远程库:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    $ git push origin master
    Enumerating objects: 22, done.
    Counting objects: 100% (22/22), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (20/20), done.
    Writing objects: 100% (20/20), 1.74 KiB | 890.00 KiB/s, done.
    Total 20 (delta 9), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (9/9), completed with 1 local object.
    To github.com:Xuan-Van/learngit.git
    49a82cf..42ab936 master -> master

    $ git push origin dev
    Enumerating objects: 8, done.
    Counting objects: 100% (8/8), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (5/5), done.
    Writing objects: 100% (6/6), 561 bytes | 561.00 KiB/s, done.
    Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (2/2), completed with 1 local object.
    remote:
    remote: Create a pull request for 'dev' on GitHub by visiting
    remote: https://github.com/Xuan-Van/learngit/pull/new/de
    remote:
    To github.com:Xuan-Van/learngit.git
    * [new branch] dev -> dev

    报错:

    Connection reset by 20.205.243.166 port 22
    fatal: Could not read from remote repository.
    
    Please make sure you have the correct access rights
    and the repository exists.
    

    参考教程:坑:ssh: connect to host github.com port 22: Connection refused
    原因:22 端口被占用,改用 443 端口,在 ~/.ssh 下添加 config 文件,内容为:

    Host github.com
      Hostname ssh.github.com
      Port 443
    

    之后执行 ssh -T git@github.com 来测试和 GitHub 的通信是否正常。
    master 分支是主分支,要时刻与远程同步;dev 分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug 分支只用于在本地修复bug,就没必要推到远程了;feature 分支是否推到远程,取决于是否和团队成员合作在上面开发。

  4. 抓取分支,将远程仓库克隆到本地:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ git clone git@github.com:Xuan-Van/gitskills.git
    Cloning into 'gitskills'...
    remote: Enumerating objects: 3, done.
    remote: Counting objects: 100% (3/3), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    Receiving objects: 100% (3/3), done.

    $ cd gitskills/
    $ git branch
    * main
  5. 要在 dev 分支上开发,就必须创建远程 origindev 分支到本地:
    1
    2
    3
    $ git checkout -b dev origin/dev
    branch 'dev' set up to track 'origin/dev'.
    Switched to a new branch 'dev'
  6. dev 上继续修改,然后把 dev 分支 push 到远程:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $ vim env.txt
    $ git add env.txt
    $ git commit -m "add env"
    [dev d7a32aa] add env
    1 file changed, 1 insertion(+)
    create mode 100644 env.txt

    $ git push origin dev
    Enumerating objects: 4, done.
    Counting objects: 100% (4/4), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 283 bytes | 283.00 KiB/s, done.
    Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    To github.com:Xuan-Van/gitskills.git
    096ff39..d7a32aa dev -> dev
  7. 如果团队成员 A 已经向 origin/dev 分支推送了提交,而碰巧团队成员 B 也对同样的文件作了修改,并试图推送:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ cat env.txt
    env

    $ git add env.txt
    $ git commit -m "add new env"
    [dev 9e457d3] add new env
    1 file changed, 1 insertion(+), 1 deletion(-)

    $ git push origin dev
    To github.com:Xuan-Van/gitskills.git
    ! [rejected] dev -> dev (fetch first)
    error: failed to push some refs to 'github.com:Xuan-Van/gitskills.git'
    hint: Updates were rejected because the remote contains work that you do not
    hint: have locally. This is usually caused by another repository pushing to
    hint: the same ref. If you want to integrate the remote changes, use
    hint: 'git pull' before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  8. 出现冲突,推送失败,先抓取最新提交:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ git pull
    remote: Enumerating objects: 5, done.
    remote: Counting objects: 100% (5/5), done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (3/3), 914 bytes | 17.00 KiB/s, done.
    From github.com:Xuan-Van/gitskills
    d7a32aa..ae0f3cf dev -> origin/dev
    Auto-merging env.txt
    CONFLICT (content): Merge conflict in env.txt
    Automatic merge failed; fix conflicts and then commit the result.

    可能因为没有指定本地 dev 分支与远程 origin/dev 分支的链接而出现抓取失败(no tracking information),需要设置 devorigin/dev 的链接:git branch --set-upstream-to=origin/dev dev

  9. 解决冲突后提交,并上传到远程仓库:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    $ cat env.txt
    <<<<<<< HEAD
    env
    =======
    env.
    >>>>>>> ae0f3cf38645e15cae7e3c2349d03a71385838a9

    $ vim env.txt
    $ git add env.txt
    $ git commit -m "fix env conflict"
    [dev dc107ec] fix env conflict

    $ git push origin dev
    Enumerating objects: 8, done.
    Counting objects: 100% (8/8), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (4/4), 396 bytes | 396.00 KiB/s, done.
    Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (1/1), done.
    To github.com:Xuan-Van/gitskills.git
    ae0f3cf..dc107ec dev -> dev

5.7 Rebase

  1. 提交了两次 hello.py后的分支形状:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    $ git log --graph --pretty=oneline --abbrev-commit
    * 84091cc (HEAD -> master) del the first line
    * aa35a6f add 'the'
    * 1d3ab8a (origin/master) del author
    * 6bdaa2d del hello
    * d5af4d8 merge branch 'master' of github
    |\
    | * 2bd33ff Create hello.py
    * | 395b305 add author
    * | e5f6e7a add comment
    |/
    * 42ab936 merged bug fix 101
    |\
    | * 092f44e fix bug 101
    |/
    * 98f7914 merge with no-ff
    |\
    | * 8cca272 add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file
  2. 尝试推送本地分支:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git push origin master
    To github.com:Xuan-Van/learngit.git
    ! [rejected] master -> master (fetch first)
    error: failed to push some refs to 'github.com:Xuan-Van/learngit.git'
    hint: Updates were rejected because the remote contains work that you do not
    hint: have locally. This is usually caused by another repository pushing to
    hint: the same ref. If you want to integrate the remote changes, use
    hint: 'git pull' before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  3. 推送失败,先抓取:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ git pull
    remote: Enumerating objects: 5, done.
    remote: Counting objects: 100% (5/5), done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (3/3), 971 bytes | 25.00 KiB/s, done.
    From github.com:Xuan-Van/learngit
    1d3ab8a..e45f5f4 master -> origin/master
    Merge made by the 'ort' strategy.
    hello.py | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)
  4. 解决冲突,查看仓库状态:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 3 commits.
    (use "git push" to publish your local commits)

    nothing to commit, working tree clean

    $ git log --graph --pretty=oneline --abbrev-commit
    * d691b01 (HEAD -> master) Merge branch 'master' of github
    |\
    | * e45f5f4 (origin/master) print(Hello World!")
    * | 84091cc del the first line
    * | aa35a6f add 'the'
    |/
    * 1d3ab8a del author
    * 6bdaa2d del hello
    * d5af4d8 merge branch 'master' of github
    |\
    | * 2bd33ff Create hello.py
    * | 395b305 add author
    * | e5f6e7a add comment
    |/
    * 42ab936 merged bug fix 101
    |\
    | * 092f44e fix bug 101
    |/
    * 98f7914 merge with no-ff
    |\
    | * 8cca272 add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file
  5. 把分叉的提交历史“整理”成一条直线,看上去更直观:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    $ git rebase
    Successfully rebased and updated refs/heads/master.

    $ git log --graph --pretty=oneline --abbrev-commit
    * 796188b (HEAD -> master) del the first line
    * 127236a add 'the'
    * e45f5f4 (origin/master) print(Hello World!")
    * 1d3ab8a del author
    * 6bdaa2d del hello
    * d5af4d8 merge branch 'master' of github
    |\
    | * 2bd33ff Create hello.py
    * | 395b305 add author
    * | e5f6e7a add comment
    |/
    * 42ab936 merged bug fix 101
    |\
    | * 092f44e fix bug 101
    |/
    * 98f7914 merge with no-ff
    |\
    | * 8cca272 add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file

    报错:可能会因为本地和远程都对同一个文件进行了修改而无法 git rebase,需要解决冲突后git add 冲突文件名git rebase --continue即可。

  6. 把本地分支推送到远程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    $ git push origin master
    Enumerating objects: 8, done.
    Counting objects: 100% (8/8), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (6/6), done.
    Writing objects: 100% (6/6), 544 bytes | 544.00 KiB/s, done.
    Total 6 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (4/4), completed with 2 local objects.
    To github.com:Xuan-Van/learngit.git
    e45f5f4..796188b master -> master

    $ git log --graph --pretty=oneline --abbrev-commit
    * 796188b (HEAD -> master, origin/master) del the first line
    * 127236a add 'the'
    * e45f5f4 print(Hello World!")
    * 1d3ab8a del author
    * 6bdaa2d del hello
    * d5af4d8 merge branch 'master' of github
    |\
    | * 2bd33ff Create hello.py
    * | 395b305 add author
    * | e5f6e7a add comment
    |/
    * 42ab936 merged bug fix 101
    |\
    | * 092f44e fix bug 101
    |/
    * 98f7914 merge with no-ff
    |\
    | * 8cca272 add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file

6 标签管理

6.1 创建标签

  1. 在需要打标签的分支上打一个新标签:

    1
    $ git tag v1.0
  2. 查看所有标签:

    1
    2
    $ git tag
    v1.0
  3. 向历史提交打标签:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    $ git log --graph --pretty=oneline --abbrev-commit
    * 796188b (HEAD -> master, tag: v1.0, origin/master) del the first line
    * 127236a add 'the'
    * e45f5f4 print(Hello World!")
    * 1d3ab8a del author
    * 6bdaa2d del hello
    * d5af4d8 merge branch 'master' of github
    |\
    | * 2bd33ff Create hello.py
    * | 395b305 add author
    * | e5f6e7a add comment
    |/
    * 42ab936 merged bug fix 101
    |\
    | * 092f44e fix bug 101
    |/
    * 98f7914 merge with no-ff
    |\
    | * 8cca272 add merge
    |/
    * 1b8779e conflict fixed
    |\
    | * 3bc9c41 AND simple
    * | 4d30980 & simple
    |/
    * cbcac43 branch test
    * 49a82cf remove test.txt
    * e309196 add test.txt
    * f896b61 git tracks changes of ilfes
    * a914ff6 git tracks changes
    * 26c8682 understand how stage works
    * 97b0ca9 add GPL
    * daaf95b add distributed
    * 15ae68d wrote a readme file

    $ git tag v0.9 d5af4d8
    $ git tag
    v0.9
    v1.0
  4. 查看标签信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $ git show v0.9
    commit d5af4d8c2540a7a9aeae09fe8d9a5814c9d43ced (tag: v0.9)
    Merge: 395b305 2bd33ff
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sun Nov 10 20:29:14 2024 +0800

    merge branch 'master' of github

    diff --cc hello.py
    index 3793d4e,ce01362..fd2de04
    --- a/hello.py
    +++ b/hello.py
    @@@ -1,2 -1,1 +1,3 @@@
    + hello
    +comment
    +author
  5. 创建带有说明的标签,用 -a 指定标签名,-m 指定说明文字:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    $ git tag -a v0.1 -m "version 0.1 released" 97b0
    $ git show v0.1
    tag v0.1
    Tagger: Xuan-Van <wuqi7137@qq.com>
    Date: Mon Nov 11 09:53:05 2024 +0800

    version 0.1 released

    commit 97b0ca9d0b01a5834c25e9aa54aff5d7d7150d73 (tag: v0.1)
    Author: Xuan-Van <wuqi7137@qq.com>
    Date: Sat Oct 26 17:53:32 2024 +0800

    add GPL

    diff --git a/readme.txt b/readme.txt
    index 9247db6..8443d23 100644
    --- a/readme.txt
    +++ b/readme.txt
    @@ -1,2 +1,2 @@
    Git is a distributed version control system.
    -Git is free software.
    +Git is free software distributed under the GPL.

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

6.2 操作标签

  1. 删除标签:

    1
    2
    $ git tag -d v0.1
    Deleted tag 'v0.1' (was 947237b)
  2. 推送某个标签到远程:

    1
    2
    3
    4
    $ git push origin v1.0
    Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    To github.com:Xuan-Van/learngit.git
    * [new tag] v1.0 -> v1.0
  3. 推送所有标签到远程:

    1
    2
    3
    4
    $ git push origin --tags
    Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    To github.com:Xuan-Van/learngit.git
    * [new tag] v0.9 -> v0.9
  4. 删除本地标签和远程标签:

    1
    2
    3
    4
    5
    6
    $ git tag -d v0.9
    Deleted tag 'v0.9' (was d5af4d8)

    $ git push origin :refs/tags/v0.9
    To github.com:Xuan-Van/learngit.git
    - [deleted] v0.9

7 自定义 Git

git config --global color.ui true 让 Git 显示颜色,使命令输出看起来更醒目。

7.1 忽略特殊文件

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

     # Windows:
     Thumbs.db
     ehthumbs.db
     Desktop.ini
    
  2. 忽略 Python 编译产生的 .pyc.pyodist 等文件或目录:

     # Python:
     *.py[cod]
     *.so
     *.egg
     *.egg-info
     dist
     build
    
  3. 加上自己定义的文件,最终得到一个完整的 .gitignore 文件:

     # Windows:
     Thumbs.db
     ehthumbs.db
     Desktop.ini
    
     # Python:
     *.py[cod]
     *.so
     *.egg
     *.egg-info
     dist
     build
    
     # My configurations:
     db.ini
     deploy_key_rsa
    
  4. 不需要从头写 .gitignore 文件,只需要组合 github/gitignore 的各种配置文件就可以使用了。.gitignore 文件本身应该提交给 Git 管理,这样可以确保所有人在同一项目下都使用相同的 .gitignore 文件。检验 .gitignore 的标准是 git status 命令是不是说 working directory clean

  5. .gitignore 忽略的文件无法添加到 Git,需要使用 git add -f 文件名 来强制添加,或者使用 git check-ignore -v 文件名 来检查 .gitignore 中的问题并修订。

  6. 当编写了规则排除了部分文件时:

     # 排除所有.开头的隐藏文件:
     .*
     # 排除所有.class文件:
     *.class
    

    但是 .* 这个规则把 .gitignore 也排除了,并且 App.class 需要被添加到版本库,但是被 *.class 规则排除了。可以添加两条例外规则:

     # 排除所有.开头的隐藏文件:
     .*
     # 排除所有.class文件:
     *.class
    
     # 不排除.gitignore和App.class:
     !.gitignore
     !App.class
    
  7. 可以通过 Git Ignore Online Generator 在线生成 .gitignore 文件并直接下载。.gitignore 文件放在哪个目录下,就对哪个目录(包括子目录)起作用。

7.2 配置别名

  1. st 表示 statusco 表示 checkoutci 表示 commitbr 表示 branch
    1
    2
    3
    4
    $ git config --global alias.st status
    $ git config --global alias.co checkout
    $ git config --global alias.ci commit
    $ git config --global alias.br branch
    --global 参数是全局参数,也就是这些命令在这台电脑的所有 Git 仓库下都有用。如果不加,那只针对当前的仓库起作用。
  2. unstage 来表示 reset HEAD(把暂存区的修改撤销掉,重新放回工作区),用 last 来表示 log -1(显示最后一次提交信息):
    1
    2
    $ git config --global alias.unstage 'reset HEAD'
    $ git config --global alias.last 'log -1'
  3. 甚至配置长命令:
    1
    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"
  4. 每个仓库的 Git 配置文件都放在 .git/config 文件中:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ cat .git/config
    [core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
    [remote "origin"]
    url = git@github.com:Xuan-Van/learngit.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "master"]
    remote = origin
    merge = refs/heads/master
    别名就在 [alias] 后面,要删除别名,直接把对应的行删掉即可。
  5. 当前用户的 Git 配置文件放在用户主目录下的一个隐藏文件 .gitconfig 中:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ cd ~/
    $ cat .gitconfig
    [user]
    name = Xuan-Van
    email = wuqi7137@qq.com
    [gui]
    recentrepo = C:/Users/21830/Desktop/Project/learngit
    [color]
    ui = true
    配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置,或者直接删掉配置文件错误的那一行。

7.3 报错

  1. 使用 HTTPS 协议克隆时出现:SSL certificate problem: unable to get local issuer certificate
    解决:git config --global http.sslbackend schannel
    作用:这条命令设置了 Git 在进行 HTTPS 请求时使用的 SSL 后端为 schannel。schannel 是 Windows 操作系统内置的安全支持提供者(Security Support Provider, SSP)。当 Git 需要进行安全的 HTTPS 通信时,它将使用 Windows 的 schannel 而不是 OpenSSL。这在某些情况下可能有助于提高性能或解决与 OpenSSL 相关的问题。
  2. 【完美解决】GitHub连接超时问题 Recv failure: Connection was reset

【Git 入门】动手学习 Git
http://xuan-van.github.io/新手入门/【git-入门】动手学习-git/
作者
文晋
发布于
2024年11月20日
许可协议