What is Git?
Git 是文件分布式管理系统。每一个文件都有对应的hash,任何对文件的更改都可以被记录下来。
Git 在local和remote都有保存代码库,可以有效防止代码丢失。
Master(main) 即是project主线,branch支线。主线支线可以合并。
Git 强大的version control可以使开发者自由地切换版本。
Git的submodule功能解决了共享dependency的问题,减少了代码的重复。
一个git project可以想象成一棵树,每个节点都有一个对应的版本(hash id),我们可以沿着树枝切换到不同的版本上。
常见概念
远程分支 origin
git log 查看历史
查看Git 历史:
git log --oneline
git log --oneline --all
git push 提交代码
提交代码时首先要和上游更新,再提交,否则会报错(因为git log不一样)。
git push
如果想强行提交用 git push --force
git diff
git diff --cached ./path/to/file
When git diff is invoked with the --cached option the diff will compare the staged changes with the local repository. The --cached option is synonymous with --staged.
git branch 新建,推送与删除
git stash
git stash
git stash pop
暂时将手头上的工作放在一边
在开发的许多时候我们都需要使用git提供的分支管理功能。
1.新建本地分支:git checkout -b test
新建一个名为:test 的本地分支。
2.提交本地分支:git push origin test:test
将本地的test分支推送到远程仓库的test 分支上。(test:test中的第一个的test表示本地分支名字,第二个test表示远程分支名字)
3.删除本地分支:git branch -D test
删除本地的分支
4.删除远程分支:git push origin :test
本命令推送了一个空的分支到远程的test分支,等同于删除远程分支。
Rebase vs Merge
Merge 两个branch会产生非线性的git log。
Rebase 后提交历史是线性的,更清晰明了。
在团队开发中,我更倾向于用rebase. Never use merge, make your life easy!
git checkout branch,pull时用 git pull --rebase
push 时如果更改了log tree 需要force push: git push --force
https://git-scm.com/book/be/v2/Git-Branching-Rebasing
如何找到代码的作者(背锅侠)
git blame file_name
如何把branch 上的更新push到master上?(cherry pick)
push的granularity把握好:整理commit,squash后,把主要的更新push到master上。
git rebase -i
把需要的commit 放在最上方. squash the redundent commit using s.
use f (fix) also works.查看某一个commit是什么?
git show hash_id
https://blog.csdn.net/w57685321/article/details/86597808push需要的commit到master
git push origin hash:master
如何在branch上pull master?
- 将master set 成upstream,这样master有更新时,
git pull --rebase
可以更新整个log tree。
git branch --set-upstream-to=origin/<branch>
如何在branch 上pull 指定branch?
git pull origin <remote_branch_name> --rebase
撤回commit
git reset --hard HEAD^
撤回git pull
git reflog
git reset --hard hash_id
关于 git submodule (子模块)
https://git-scm.com/book/en/v2/Git-Tools-Submodules
https://zhuanlan.zhihu.com/p/87053283
submodule 是git一个很好的新功能,解决了library dependency的问题。面对复杂的项目,我们因为开发需要将代码拆解成不同的子模块。主项目对子模块有依赖关系,但开发过程相对独立。 当main project需要include sub-project 时,我们无需copy sub-project到当前project下,只需sub-project设为main project的submodule。这样main project 和 sub project 的版本管理可以互相独立。当sub project 更新时,我们只需在main project里git submodule update.
子模块内容的更新:
- 本地有更新
- 本地submodule 版本有更新
- 远程有更新
Add a submodule
An HTTPS URL like https://github.com/user/repo.git
An SSH URL, like git@github.com:user/repo.git
Use ssh url when possible.
git submodule [--quiet] add [<options>] [--] <remote_repo_url> [<local_path>]
.gitmodule config file is created.
[submodule "third_party/abseil-cpp"]
path = third_party/abseil-cpp # local directory of the submodule
url = git@github.com:abseil/abseil-cpp.git # remote submodule url (can be absoule or relative url)
git commit -am "add new submodule"
git push origin master
Delete a submodule
# 逆初始化模块,其中{MOD_NAME}为模块目录,执行后可发现模块目录被清空
git submodule deinit {MOD_NAME}
# 删除.gitmodules中记录的模块信息(--cached选项清除.git/modules中的缓存)
git rm --cached {MOD_NAME}
# 提交更改到代码库,可观察到'.gitmodules'内容发生变更
git commit -am "Remove a submodule."
Commit message
$ git commit -am 'Add DbConnector module'
[master fb9093c] Add DbConnector module
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 DbConnector
Notice the 160000 mode for the DbConnector entry. That is a special mode in Git that basically means you’re recording a commit as a directory entry rather than a subdirectory or a file.
Clone a project with submodules
By default, when you clone a project with submodules, you only get the directories but no files.
git clone --recurse-submodules project_url
or
git submodule init # register to the remote submodule path
git submodule update --recurse-submodules # downloading submodule files
--recurse-submodules automatically initialize and update nested submodules.
Fool Proof (in case you forgot):
git submodule update --init --recursive
Working with submodules
1. Submodule User - Pulling changes from submodules or projects with submodules
git submodule update --remote: pull the lastest changes based on the remote submodule.
if no --remote is added, it pulls the most recent updates from the main module.
git config -f .gitmodules submodule.DbConnector.branch stable # change the branch of the submodule to update for everyone(by changing the .gitmodules file)
note: This command will by default assume that you want to update the checkout to the master branch of the submodule repository.
git pull
does not update the submodules by default!!!
Always use git submodule update --init --recursive
after each git pull.
2. Submodule Dev - Publishing submodule changes
making changes to the main project and the submodule at the same time.
Recommend to work on the submodule in its own repo to avoid confusion.(Simplify our life rather than complicate the shit!)
$ git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
DbConnector
Please try
git push --recurse-submodules=on-demand
or cd to the path and use
git push
to push them to a remote.
Submodule Foreach
Other Commands
在主repo查看submodule的commit hash id
git submodule
初始化submodule
git submodule update --init submodule_path
更新某个submodule
git submodule update --remote submodule_path
update single submodule
git submodule update --init <specific relative path to submodule>
更新所有submodule
git pull --recurse-submodules
用这个方法更新后,submodule的version和main repo HEAD指定各submodule的version一样。
redo commit
git reset --soft HEAD~
git push -f