Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

课程笔记: 玩转 Git 三剑客 (苏玲) #307

Open
nonocast opened this issue Jul 1, 2022 · 0 comments
Open

课程笔记: 玩转 Git 三剑客 (苏玲) #307

nonocast opened this issue Jul 1, 2022 · 0 comments

Comments

@nonocast
Copy link
Owner

nonocast commented Jul 1, 2022

version: git 2.37.0

三剑客

  • git
  • GitHub
  • GitLab

git

git 怎么配置?

通过git config命令实现,配置分为local, global, system 3个级别, 通过--list查看对应的配置:

~ git config --list (当前上下文下的合并配置, 即system+global+local, 局部优先)
~ git config --list --local (仅针对当前仓库)
~ git config --list --global (对当前用户下所有仓库有效)
~ git config --list --system (对所有用户有效)
  • system: linux在/etc, macOS通过brew安装后则在/opt/homebrew/etc
  • global: 对应到~/.gitconfig
  • local: 对应到仓库目录.git/config
  • 随时通过git config --listgit config -l查看当前配置

为什么要配置user.name和user.email?

一般安装后都需要配置global user, 如下:

~ git config --global user.name 'your_name'
~ git config --global user.email '[email protected]'

主要是因为git commit时需要填写name/email标识提交人,如果没有配置,git会根据当前系统的username和hostname自动生成,这显然不是我们希望的:

git101 git:(main) ✗ git commit -m "whatever"
[main cc0ff5d] whatever
 Committer: nonocast <[email protected]>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email [email protected]

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 1 insertion(+)
  • 你可以通过不同的身份进行commit,通过git log可以查看提交者信息。
  • 通常情况下,你会在不同的环境下采用不同的身份进行提交,比如公司项目就需要采用公司邮箱,否则代码统计不到你,而社区则会采用社会化身份,所以要仔细设定不同项目的提交身份。

git 本地仓库怎么提交?

git本地仓库分为3个区域:

  • 工作区 (working directory)
  • 暂存区 (staging area)
  • 仓库区 (repository .git)

一般情况下,通过git add将工作区内容加入到暂存区,然后通过git commit将暂存区提交仓库区。

如何放弃暂存区的所有修改?

比如git add修改文件,或者做了mv操作等等,只要我没有commit,那么就可以直接通过git reset --hard撤回到原先状态。

怎么查看git log?

  • git log: 所有commit的完整信息 (默认当前分支)
  • git log -n4: 最近2次commit的完整信息
  • git log --oneline: 所有commit仅message
  • git log -n4 --oneline: 最近4次commit的message
  • git log --all (所有分支)
  • git log --all --graph
  • git log --all --graph --oneline
  • git log --online --all -n4 --graph: 查看所有分支上最近4个commit

可以通过git help loggit help --web log查看进一步的帮助。

怎么创建切换branch?

  • 创建分支: git branch branch-name
  • 切换分支: git checkout branch-name
  • 创建同时切换分支: git checkout -b new-branch-name
  • 查看分支: git branch

什么tig?

tig - text-mode interface for Git

tig        [options] [revisions] [--] [paths]
tig log    [options] [revisions] [--] [paths]
tig show   [options] [revisions] [--] [paths]
tig reflog [options] [revisions]
tig blame  [options] [rev] [--] path
tig grep   [options] [pattern]
tig refs   [options]
tig stash  [options]
tig status
tig <      [Git command output]

如何修改过往commit的meessage?

16 | 怎么修改老旧commit的message?

  • 开启rebase过程, git rebase -i commitid, 这里填写目标commit的parent commitid
  • 在rebase交互过程中将目标commit从pick改为reword
  • 在reword中修改message

怎样把连续的多个commit整理为1个commit?

17 | 怎样把连续的多个commit整理成1个?

  • 比如现在有commit c1-c6, 现在需要将c2-c4合并,则git rebase -i c1
  • 将c3,c4从pick改为squash,即将c3,c4的内容meld给c2

怎样把间隔的多个commit整理为1个commit?

18 | 怎样把间隔的几个commit整理成1个?

  • 比如现在有 commit c1-c5, 现在需要将c3和c5合并,则git rebase -i c2
  • 将commit顺序c2,c3,c4,c5改为c2,c3, c5, c4, 同时将c5改为squash

怎么比较暂存区和HEAD的差异?

  • git diff --cached

怎么比较工作区和暂存区的差异?

  • 查看所有差异: git diff
  • 查看特定文件的差异: git diff -- readme.md index.html

如何让暂存区恢复成和HEAD的一样?

  • 恢复暂存区,不改变工作区: git reset HEAD
  • 恢复暂存区的同时,也将工作区恢复为HEAD: git reset --hard HEAD

如何让工作区的文件恢复为和暂存区一样?

  • git checkout -- readme

reset and checkout

  • 改变暂存区: git reset
  • 改变工作区: git checkout

取消最近的几次提交?

比如有c1,c2,c3, 现在HEAD指向c3,然后通过git reset --hard c1,此时工作区恢复为c1, 暂存区清空, HEAD指向c1。

git支持哪些同步协议?

Git - The Protocols

  • Local Protocol: git clone /srv/git/project.gitgit clone --bare /srv/git/project/.git
  • The HTTP Protocol: smart HTTP and Dumb HTTP, 优先采用smart HTTP
  • The SSH Protocol: git clone ssh://[user@]server/project.git
  • The Git Protocol: git clone git://server/project.git

注:

  • project.git指bare repository,即没有working directory
  • smart有传输进度,dumb没有

git是如何考虑多个仓库的同步的?

一个git仓库可以通过git remote管理和外部仓库的连接, 如下:

# hello
~ git init hello && cd hello
Initialized empty Git repository in /.../hello/.git/
~ echo "hi,hello" > hello.md 
~ git add hello.md 
~ git commit -m "initial hello.md"
[main (root-commit) e2d4af5] initial hello.md
 1 file changed, 1 insertion(+)
 create mode 100644 hello.md

# foo
~ git init foo && cd foo
Initialized empty Git repository in /.../foo/.git/
~ echo "hi,foo" > foo.md 
~ git add foo.md 
~ git commit -m "initial foo.md"
[main (root-commit) 324e318] initial foo.md
 1 file changed, 1 insertion(+)
 create mode 100644 foo.md

# 同样的方式建立bar repo

此时目录下有hello, foo, bar三个仓库,各自有一个md,然后通过git remote 建立连接:

~ git remote add foo ../foo
~ git remote add bar ../bar
~ git remote 
bar
foo
~ git remote -v
bar	../bar (fetch)
bar	../bar (push)
foo	../foo (fetch)
foo	../foo (push)

通过git fetch就可以将远端的内容复制到本地仓库:

~ git fetch foo
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 187 bytes | 187.00 KiB/s, done.
From ../foo
 * [new branch]      main       -> foo/main
~ git fetch bar
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 191 bytes | 191.00 KiB/s, done.
From ../bar
 * [new branch]      main       -> bar/main
~ git branch -av
* main             56e8d74 initial hello
  remotes/bar/main 775d204 initial bar
  remotes/foo/main 986eac5 initial foo
  • 底层的逻辑依然是非常清晰的,就是每个仓库管好自己的branch, commit,然后如果添加remote,则将远端的仓库全部拉到本地形成副本,副本以remote name作为prefix,即foo/main, bar/main,互不干扰。

  • 在这个逻辑之上,我们来考虑如何关联hello/main和foo/main两个分支的关联。

  • git fetch foo, Download objects and refs from another repository, 即包括tree, commit, branch, tag, blob等等

  • git fetch foo main, 只取和main有关的objects和refs,对应的分支命名为: foo/main

  • 命令格式: git fetch <远程主机名> <分支名>, 以git fetch origin main为例,即获取origin远端仓库的main分支下所有相关内容

  • 基于git branch <new_branch> [from_branch], 可以git branch foo foo/main, 或者git checkout -b foo foo/main

  • 当然你可以直接将fetch回来的foo/main和本地仓库的main合并(merge),即直接得到了别人的代码,git merge foo/main, 实践中需要git merge foo/main --allow-unrelated-histories

  • git pull <远程主机名> <远程分支名>:<本地分支名>, 本质上就是pull然后merge

  • 此时就应该在本地仓库main分支下git pull foo main

  • 借助git branch --set-upstream main origin/main建立追踪关系后,就可以省略为git pull foo

  • 又因为当前分支只有一个upstream时可以省略remote,所以就简化成最终的git pull,其实本意是git pull foo main,再展开就是git fetch, 然后git merge

参考教程

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant