Git

Git #

分支 #

# 本地仓库 分支引用
refs/heads/v1.0.0
# 远程跟踪分支引用, 远程仓库 origin 中有一个分支 v1.0.0
refs/remotes/origin/v1.0.0

# 标签引用,包括远程和本地
refs/tags/v1.0.0

tag #

  • 远程 tag 被视为本地 tag 的一种,它们都存储在 refs/tags/ 路径下。当你从远程仓库拉取或推送 tag 时,Git 会自动同步这些 tag 到本地仓库中的 refs/tags/ 路径

分支和 tag 重名 #

远程有个 v1.0.0 tag,想基于它拉一个远程 v1.0.0 分支 #

# 本地拉 v1.0.0 tag
git fetch origin tag v1.0.0
# git fetch origin --tags

# 基于 tag 拉 v1.0.0 分支,
# git co -b 分支名 tag名
git co -b v1.0.0 v1.0.0

# 把本地分支推送到远程分支
git push origin refs/heads/v2.11.3:refs/heads/v2.11.3

原理:

git show-ref v2.11.3

git module #

git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f

更新 submodule #

git submodule update --init

git submodule update --remote

merge vs squash vs rebase #

merge 不能保持 master 分支干净,但是保持了所有的 commit history,大多数情况下都是不好的,个别情况挺好 squash 也可以保持 master 分支干净,但是 master 中 author 都是 maintainer,而不是原 owner rebase 可以尽可能保持 master 分支干净整洁,并且易于识别 author

squash merge #

# 切换到目标分支
$ git checkout master

# 以 squash 的形式 merge
$ git merge --squash devel

# it does not produce a commit right away: you need an additional commit
$ git commit -m "squash branch"
  • 你会发现,在 master 分支上居然有未提交的修改,然后你就需要在 master 上主动提交了修改,
  • 注意,这里是你 commit 的,也就是改变了 commit 的 author。
  • git merge has a –commit option, but it cannot be used with –squash.
  • It was never possible to use –commit and –squash together.

参考:

rebase merge #

# 先切换到 devel 分支(不一样咯)
$ git checkout devel

# 变基
$ git rebase -i master

# 切换回目标分支
$ git checkout master

# 合并
$ git merge
  • 我们在 devel 里面对照 master 进行了变基
    • 所谓的变基其实就是找到两个分支共同的祖先
  • 然后在当前分支上合并从共同祖先到现在的所有 commit
    • 会选择怎么处理这些 commit
  • 然后我们就得到了一个从公共 commit 到现在的单个 commit
  • 这个时候别人将我们这个 commit 合并到 master 也只会在 master 上留下一个 commit 记录

合并 git commit #

参考:


git branch 与 git tag 同名 #

需要使用完整路径

git checkout refs/heads/v1.5.2

git checkout refs/tags/v1.5.2

git push -u origin refs/heads/v4.8.0

参考:


git pull force #

git fetch --all

# git reset --hard origin/<branch_name>
git reset --hard origin/master

参考:


hard reset vs mixed reset vs soft reset #

# 回到 reset 版本,之后的文件都属于 git add 的状态
git reset --soft

# git reset 默认就是 --mixed
# 回到 reset 版本,之后的文件都属于 git add 前的状态
git reset --mixed

# 回到 reset 版本,之后文件都丢弃(使用 git reflog 可以找回来)
git reset --hard

git reflog #

reflog 是 Git 操作的一道安全保障,它能够记录几乎所有本地仓库的改变。

包括所有分支 commit 提交,已经删除的 commit(其实并未被实际删除)都会被记录。

只要 HEAD 发生变化,就可以通过 reflog 查看到。

git 回退 #

# 文件放弃本地修改
git checkout -- <file>

# 回退到某个版本
git checkout commit-id <path>
git reset -- <path>

参考:


config 权限 #

问题: Bad owner or permissions on ~/.ssh/config

解决:

chown $USER ~/.ssh/config
chmod 644 ~/.ssh/config

git submodule #

拉取 submodule #

git submodule init
git submodule update --remote

git submodule add -b #

参考:

submodule 修改 url #

  • edit the .gitmodules file to update the URL
  • git submodule sync

参考: How to change the remote repository for a git submodule?

delete submodule #

  • Delete the relevant section from the .gitmodules file.
  • Stage the .gitmodules changes git add .gitmodules
  • Delete the relevant section from .git/config.
  • Run git rm --cached path_to_submodule (no trailing slash).
  • Run rm -rf .git/modules/path_to_submodule (no trailing slash).
  • Commit git commit -m "Removed submodule "
  • Delete the now untracked submodule files rm -rf path_to_submodule

参考:


untracked status #

[submodule "example"]
    path = example
    url = git://github.com/ikingye/example.git
    ignore = dirty

教程 #

pcottle/learnGitBranching Github stars Github forks Language Last Tag Last commit #

LearnGitBranching is a git repository visualizer, sandbox, and a series of educational tutorials and challenges.

https://learngitbranching.js.org/


常见问题 #

保留 remote 的历史记录,但是不关心未来这个文件的变化 #

比如某个文件频繁变化,希望不再管理后续更新。

git update-index --assume-unchanged xxx-filepath

# 继续跟进变化
git update-index --no-assume-unchanged xxx-filepath

本文访问量

本站总访问量

本站总访客数