快速参考
- 1. git常用指令
- 2. gitlab
- 2. ssh指令
- 3. dh_make
- 4. gitbook
- 5. clang-format
1. git常用指令
# 在本地用户(root和user是两个用户)设置自己gitlab账户的用户名和密码,${GIT_USER_NAME}替换为自己的gitlab账户名,${GIT_USER_PASSWD}替换为自己的gitlab账户密码(用于CPMAddPackage克隆指定的仓库)
git config --global credential.helper store
echo "http://${GIT_USER_NAME}:${GIT_USER_PASSWD}@git.aubo-robotics.cn:8001" > ~/.git-credentials
# 创建仓库 用于把当前所在目录(如果你使用 Windows 系统,为了避免遇到各种莫名其妙的问题,请确保各级目录名不包含中文)变成 git 可以管理的仓库
git init
# 添加文件 git add
# 添加一个或多个文件到暂存区
git add [file1] [file2] ...
# 添加指定目录到暂存区,包括该目录中的子目录
git add [dir]
# 同时添加文件和目录:
git add [dir] [file]
# 添加当前目录下的所有文件到暂存区:
git add .
# 删除文件 git rm
# 用于删除工作区文件,并且将这次删除放入暂存区,相当于 rm 指令与 git add 两条指令的叠加。
# 文件已提交至仓库,且工作区和暂存区均无更改
# 工作区和暂存区均删除文件
git rm [file1] [file2] ...
# 工作区和暂存区均删除整个目录
git rm -r [dir]
# 工作区和暂存区均删除所有文件和目录
git rm -r *
# 文件已提交至仓库,工作区或暂存区有更改
# - 工作区保留、暂存区删除文件,同时被删除项变为未跟踪状态
git rm --cached [file1] [file2] ...
# - 工作区保留、暂存区删除整个目录,同时被删除项变为未跟踪状态
git rm --cached -r [dir]
# - 工作区保留、暂存区均删除所有文件和目录,同时被删除项变为未跟踪状态
git rm -r *
# - 工作区和暂存区均删除文件
git rm -f [file1] [file2] ...
# - 工作区和暂存区均删除整个目录
git rm -fr [dir]
# - 工作区和暂存区均删除所有文件和目录
git rm -fr *
# 文件已添加至暂存区
# - 工作区保留、暂存区删除文件,同时文件变为未跟踪状态
git rm --cached [file1] [file2] ...
# - 工作区保留、暂存区删除整个目录,同时目录中的所有文件变为未跟踪状态
git rm --cached -r [dir]
# - 工作区保留、暂存区均删除所有文件和目录,同时被删除项变为未跟踪状态
git rm -r *
# - 工作区和暂存区均删除文件
git rm -f [file1] [file2] ...
# - 工作区和暂存区均删除整个目录
git rm -fr [dir]
# - 工作区和暂存区均删除所有文件和目录
git rm -fr *
# 注意:未跟踪的文件不能使用 git rm 来删除
# 提交,将暂存区内容提交至仓库中
# 将暂存区所有内容提交至仓库,message 是备注信息
git commit -m [message]
# 将暂存区指定文件提交至仓库,message 是备注信息
git commit [file1] [file2] ... -m [message]
# 文件已经提交至仓库,再次修改文件后不需要执行 git add 命令,直接提交至仓库
git commit -am [message]
# 编辑多行提交信息
git commit -a
# 修改提交
# 用于修改最后一次的提交信息或提交内容,commit id 会改变,用法详见下文"修改最近一次提交内容"的的方法一。
git commit --amend
# 查看状态
# 用于查看在你上次提交之后是否有对文件进行再次修改,当前仓库状态信息包含:
# 当前所在分支
# 有未跟踪的文件时会给出提示
# 有已提交至仓库中的文件再次被修改时会给出提示
git status
# 推送分支
# 一般格式
git push <远程主机名> <本地分支名>:<远程分支名>
# 若本地分支推送到与之存在追踪关系的远程分支(通常两者同名),可使用简化格式,如果该远程分支不存在,则会被新建
git push <远程主机名> <本地分支名>
# 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要 --all 选项
git push --all <远程主机名>
# 若确定本地仓库分支与远程仓库分支存在冲突,且远程仓库可覆盖,可执行
git push -f <远程主机名> <本地分支名>:<远程分支名>
# 拉取分支
# 用于从远程仓库分支获取代码并合并本地仓库分支,其实就是 git fetch 和 git merge FETCH_HEAD 指令的叠加
# 一般格式
git pull <远程主机名> <远程分支名>:<本地分支名>
# 远程分支是与当前分支合并
git pull <远程主机名> <远程分支名>
# 变基
git rebase
# 合并或修改当前分支最近的4次提交,-i表示交互式
git rebase -i HEAD~4
# 合并或修改当前分支自1234567(commit id 前7位)以来的提交,-i表示交互式
git rebase -i 1234567
# 将master分支上所有新增提交合并到当前分支,合并后,当前分支的新增提交均在 master 分支的提交之后
git rebase -i master
# rebase本地存储的origin远程对应的master分支,为了保证本地与远程一致,可以先使用git fetch origin命令
git rebase -i origin/master
# 将指定远程仓库的全部更新取回本地
git fetch <远程主机名>
# 将指定远程仓库的指定分支的更新取回本地
git fetch <远程主机名> <分支名>
# 查看历史提交
# git log 用于查看历史提交,不包含已经删除的提交记录和 git reset 的操作记录
# 输出 commit id, author, date, commit message
git log
# 仅输出 commit id 前7个字符串和 commit message
git log --oneline
# 在git log 的基础上输出文件增删改的统计数据
git log --stat
# 输出每个commit具体修改的内容,输出的形式以diff的形式给出
git log -p
# 自定义输出的信息(包含字体和颜色),感兴趣可参考 https://www.cnblogs.com/bellkosmos/p/5923439.html,此处给出 一个例子
git log --pretty="%h %cd %an ==>%s" --date=format:'%Y-%m-%d %H:%M'
# 输出结果:
# 9e36820 2021-01-17 11:11 lianglongxiao ==>测试持续集成
# 4ff2c7b 2020-10-19 18:51 lianglongxiao ==>初步完成运动参数设置过程
# 查看dev中log有的commit,而master中log没有的commit
git log dev ^master
# 用于查看历史提交,包含已经删除的提交记录和git reset的操作记录,在版本恢复中很有作用!
git reflog
# git reset 用于回退版本,可以退回某次提交的版本,
# 将全部内容从当前版本回退3个版本,保留工作区和暂存区的内容,简单来说就是变为未提交状态
git reset --soft HEAD~3
git reset --soft HEAD^^^
# 将全部内容从当前版本回退2个版本,保留工作区内容,简单来说就是变为未跟踪状态
git reset --mixed HEAD~2
git reset --mixed HEAD^^
git reset HEAD~2
# 将全部内容从当前版本回退到指定版本(commit id为1234567),工作区内容也一起回退
git reset --hard 1234567
# 将部分目录或文件从当前版本回退到指定版本(commit id 为1234567),工作区内容也一起回退
git reset --hard 1234567 [dir] [file]
# git submodule 用于将一个git仓库作为另一个git仓库的子目录。它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立
# 将已存在的 Git 仓库(url 为远程仓库地址)添加为正在工作的仓库的子模块,若不指定path,子模块会将子项目放到一个与仓库同名的目录中path
git submodule add [url] [path]
# 克隆含子模块的仓库时,克隆仓库操作完成后,用于初始化并更新子模块
git submodule update --init --recursive
# 克隆含子模块的仓库时,同步初始化并更新子模块,url为主仓库远程地址
git clone --recurse -submodules [url]
# 仓库创建完成后,日常拉取所有子模块
git submodule foreach git pull
# 子模块的远程仓库地址更新后,首先需要手动更改 .gitmodules 文件中的子模块url地址,然后将新的url复制到本地配置中
git submodule sync
# git cherry-pick 用于部分代码变动(某几个提交)从一个分支转移到另一个分支
# 将其他分支的指定提交应用于当前分支
git cherry-pick [commit id]
# 将其他分支的最新提交应用于当前分支
git cherry-pick [branch name]
# 将其他分支的多个指定提交应用于当前分支
git cherry-pick [commit id 1] [commit id 2]
# 将其他分支的A到B的所有提交(不包含A)应用于当前分支
git cherry-pick A..B
# 将其他分支的A到B的所有提交(包含A)应用于当前分支
git cherry-pick A^..B
# 注意:
# -e,--edit:打开外部编辑器,编辑提交信息
# -n,--no-commit:只更新工作区和暂存区,不产生新的提交
# -x:在提交信息的末尾追加一行(cherry picked from commit ...),方便以后查到这个提交是如何产生的
# -s,--signoff:在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作
# -m parent-number,--mainline parent-number:如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,
# 因为它不知道应该采用哪个分支的代码变动。-m 配置项告诉 git,应该采用哪个分支的变动。它的参数parent-number是一个从1开始的整数,
# 代表原始提交的父分支编号,可以从git log中查看编号
# 如果操作过程中发生代码冲突,Cherry pick 会停下来,让用户决定如何继续操作
# --continue:用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .),第二步使用 git cherry-pick --continue 命令,让 Cherry pick 过程继续执行
# --abort:发生代码冲突后,退出 Cherry pick,回到操作前的样子
# --quit:发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子
# git diff 用于比较已跟踪的文件的不同
# 显示暂存区和工作区的差异,若不指定file或dir,默认比较全部文件
git diff [file] [dir]
# 显示暂存区和版本库的差异,若不指定file或dir,默认比较全部文件
git diff --cached [file] [dir]
# 显示工作区和版本库的差异,若不指定file或dir,默认比较全部文件
git diff HEAD [file] [dir]
# 比较两个分支上最后commit的内容的差别
git diff branch1 branch2
# 比较两个分支上最后commit的指定文件的差别
git diff branch1 branch2 [file]
# 比较两个分支上最后commit的有差异的文件(不详细,没有对比内容)
git diff branch1 branch2 --stat
# git stash 用于备份当前工作区已跟踪的文件
# 当前工作区内容不具备提交条件,但此时需要切换分支、拉取代码进行其它工作,此时需要git stash保存现场,待其它工作完成后,使用git stash pop恢复现场
# 保存当前工作区的内容,保存到git栈中,工作区内容与当前版本库保持一致,save及其后内容用于标记本次stash,可省略:
git stash save "test stash"
# 显示git栈中的所有工作区内容的备份
git stash list
# 清空git栈
git stash clear
# 显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个
git stash show stash@{1}:
# 从git栈中获取到倒数第3次stash进去的内容,用以恢复工作区的内容,会删除栈中对应的stash,其中stash@{2}可以省略,表示倒数最后一次的stash
git stash pop stash@{2}
# 从git栈中获取到最后一次stash进去的内容,用以恢复工作区的内容,同时保留stash
git stash apply stash@{0}
git stash apply
# git checkout 用于切换分支或恢复工作区文件(文件必须为已跟踪状态)
# 在不改变工作区与暂存区内容的情况下,从当前分支切换到 dev 分支
git checkout dev
# 在不改变工作区与暂存区内容的情况下,创建新分支 dev,并从当前分支切换到 dev 分支
git checkout -b dev
# 把readme.txt文件在工作区的修改全部撤销
# 这里有两种情况:
# 一种是readme.txt自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态
# 一种是readme.txt已经添加到暂存区后,又作了修改,现在撤销修改就回到添加到暂存区后的状态
git checkout -- readme.txt
# 以递归方式把所有后缀名为.txt 的文件在工作区的修改全部撤销
git checkout -- "*.txt"
# 把工作区全部文件的修改全部撤销
git checkout .
# 查看所有远程仓库
get remote -v
基本开发流程
# 从远程clone仓库到本地
git clone ssh://...
# 切换到开发分支
git checkout -b <devel>
# 添加修改
git add .
# 编辑commit记录
git commit -a
# 更新远程分支(主要是更新origin/master主分支)
git fetch origin
git rebase origin/master
# 如果遇到CONFLICT冲突,在代码中解决冲突,然后
git add .
# 继续执行rebase
git rebase --continue
# 如果rebase操作失误,可以执行abort操作,取消本次rebase
git rebase --abort
# 如果在操作过程中不小心关闭窗口,可以重新打开终端,切换到仓库目录
git rebase --edit-todo
# rebase完成之后,需要push到远程的devel分支,但是由于rebase改变了devel分支的历史记录,在确保无误的问题下,需要强制push
git push -f origin <devel>
# 上述强制push有丢失更改的风险,保险起见,可以在远程新建一个分支
git push origin <devel>:<devel_fater_rebase>
自己在多台电脑上开发同一个分支
# 添加修改
git add .
# 编辑commit记录
git commit -a
# 更新远程分支到本地分支
git fetch origin
git rebase origin/<devel>
# 或者
git pull --rebase origin <devel>
# 以上操作是为了避免git pull添加不必要的commit记录,并且搞乱自己分支
# rebase完成之后,需要push到远程的devel分支,但是由于rebase改变了devel分支的历史记录,在确保无误的问题下,需要强制push
git push -f origin <devel>
# 上述强制push有丢失更改的风险,保险起见,可以在远程新建一个分支
git push origin <devel>:<devel_fater_rebase>
远程分支替换本地分支
# 拉取远程分支
git fetch origin master
# 然后使用远程分支重置本地分支
git reset --hard origin/master
# 删除您的本地分行
git branch -d master
# 获取最新的远程分支
git fetch origin master
# 重建基于远程的本地分支
git checkout -b master origin/master
修改最近一次提交内容
# 方法一: 可以修改commit message,也可以修改提交内容
#修改需要修改的地方(只是修改commit message就不用做)
git add . #这一步如果只是修改commit message不用输入
git commit --amend
# 方法二:与上面方法基本一致,也可以修改提交内容和commit message
git reset HEAD^
#修改需要修改的地方(只是修改commit message就不用做)
git add . #这一步如果只是修改commit message不用输入
git commit -m "new commit message" # 或者git commit -c ORIG_HEAD
# 方法三:提交到了错误的分支上的处理
git reset HEAD~ --soft
git stash
# 切换到正确的分支
git checkout name-of-the-correct-branch
git stash pop
git add . # 或添加特定文件
git commit -m "你的提交说明"
# 方法四:rebase
# 查看修改
git rebase -i master~1 #最后一次
git rebase -i master~5 #最后五次
git rebase -i HEAD~3 #当前版本的倒数第三次状态
git rebase -i 32e0a87f #指定的SHA位置
# 需要注意最后的^号,意思是commit id的前一次提交
git rebase -i "5b3ba7a"^
撤销
未进行git push
前的所有操作,都是在“本地仓库”中执行的。我们暂且将“本地仓库”的代码还原操作叫做“撤销”!
# 情况一:文件被修改了,但未执行git add操作(工作区内撤销)
git checkout fileName
git checkout .
# 情况二:同时对多个文件执行了git add操作,但本次只想提交其中一部分文件
git reset HEAD <filename>
# 情况三:文件执行了git add操作,但想撤销对其的修改(index内回滚)
git reset HEAD fileName # 取消暂存
git checkout fileName # 撤销修改
#情况四:修改的文件已被git commit,但想再次修改不再产生新的commit
git add sample.txt # 修改最后一次提交
git commit --amend -m "说明"
# 情况五:已在本地进行了多次git commit操作,现在想撤销到其中某次Commit
git reset [--hard|soft|mixed|merge|keep] [commit|HEAD]
具体参数和使用说明,请查看:Git Pro深入浅出(二)中的重置揭秘部分
删除子模块
rm -rf 子模块目录 删除子模块目录及源码
vi .gitmodules 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config 删除配置项中子模块相关条目
rm .git/module/* 删除模块下的子模块目录,每个子模块对应一个目录,注意只删除对应的子模块目录即可
从远端更新子模块
git submodule update --remote # 主工程中执行
以下为指令输出结果:
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 21 (delta 2), reused 1 (delta 1), pack-reused 14
展开对象中: 100% (21/21), 完成.
来自 http://git.aubo-robotics.cn:8001/arcs/arcs_env
6a04d6b..41a84a9 master -> origin/master[新分支] dev/smartpointer -> origin/dev/smartpointer 6a04d6b..30b6505 dev_lianglongxiao -> origin/dev_lianglongxiao
子模组路径 'arcs_env':检出 '41a84a9cf5654a0cae2a6638790e65c1905e3940'
cd arcs_env/ # 进入子模块arcs_env
git status # 查看子模块状态
以下为指令输出结果:
头指针分离于 41a84a9
无文件要提交,干净的工作区
git log # 查看子模块提交,41a84a9指的是远端master的最新提交
以下为指令输出结果:
41a84a9 - (HEAD -> master, origin/master, origin/HEAD) fix: 增加qt静默安装方式说明 (27 分钟前)
63e9eb1 - fix: gitlab-runner以root用户启动方式 (27 分钟前)
30b6505 - (origin/dev_lianglongxiao) feat: make_helper.sh中增加函数,用于同时打包同一个工程下的多个库或可执行程序,使用示例见nanolog模块 (47 分钟前)
git checkout master # 子模块切回master分支
以下为指令输出结果:
之前的 HEAD 位置是 41a84a9... fix: 增加qt静默安装方式说明
切换到分支 'master'
您的分支落后 'origin/master' 共 5 个提交,并且可以快进。
(使用 "git pull" 来更新您的本地分支)
git rebase origin/master # 当前分支合并master分支最新提交
以下为指令输出结果:
首先,回退分支以便在上面重放您的工作...
快进 master 至 origin/master。
cd .. # 回到主工程目录
git config status.submodulesummary 1 # 显示子模块的更改摘要,以前设置过可以跳过该指令
git status # 查看主工程状态,提示子模块有新提交
以下为指令输出结果:
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)修改: arcs_env (新提交)
子模组已修改但尚未更新:
arcs_env 6a04d6b...41a84a9 (5):
fix: 增加qt静默安装方式说明
git add . # 添加修改至暂存区
git commit -m "refactor: 更新子模块arcs_env"
本地更新子模块并推送到远端
在主工程的子模块目录中进行的修改,并且主工程要依赖子模块的更新
cd arcs_env/ # 进入子模块arcs_env
git status # 查看子模块状态
以下为指令输出结果:
位于分支 dev_lianglongxiao
您的分支领先 'origin/dev_lianglongxiao' 共 2 个提交。
(使用 "git push" 来发布您的本地提交)
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)修改: 02_cheatlist.md
修改: scripts/make_helper.sh
在子模块目录里提交、推送更新:
git add .
git commit -m "feat: 02_cheatlist.md中添加子模块更新相关的git操作说明"
git fetch
git rebase origin/master
git push -f origin dev_lianglongxiao
回到主工程目录,查看状态
cd ..
git status
以下为指令输出结果:
位于分支 dev_lianglongxiao
您的分支和 'origin/dev_lianglongxiao' 出现了偏离,
并且分别有 2 和 2 处不同的提交。
(使用 "git pull" 来合并远程分支)尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)修改: arcs_env (新提交)
子模组已修改但尚未更新:
arcs_env 41a84a9...5109863 (1):
feat: 02_cheatlist.md中添加子模块更新相关的git操作说明
在主工程目录里提交、推送更新:
git add .
git commit -m "feat: 更新arcs_env子模块"
git fetch
git rebase origin/master
git push -f origin dev_lianglongxiao
回滚到某次提交,在此基础上建立新的分支
git checkout [commit id]
将其它分支某次提交合入到本地当前分支,直接使用原始提交信息
在本地仓库中,有两个分支:branch1和branch2,我们先来查看各个分支的提交:
# 切换到branch2分支
root@ubuntu:~/auboData/gittest# git checkout branch1
# 查看提交
root@ubuntu:~/auboData/gittest# git log
552e796 - feat: brancn2 edit c (16 分钟前)
30f19ec - (origin/master, origin/HEAD, master) feat: add c (3 周前)
c3ce9ac - feat: add b (3 周前)a62306e - feat: add a (3 周前)
* c28c3a8 - Initial commit (3 周前) <梁龙晓># 切换到branch1分支 root@ubuntu:~/auboData/gittest# git checkout branch1 # 查看最近三次提交 root@ubuntu:~/auboData/gittest# git log
7d2a0e5 - feat: brancn1 edit c (17 分钟前)
30f19ec - (origin/master, origin/HEAD, master) feat: add c (3 周前) c3ce9ac - feat: add b (3 周前) a62306e - feat: add a (3 周前) * c28c3a8 - Initial commit (3 周前) <梁龙晓>
将branch2分支上的最近一次提交内容合入到branch1分支上
root@ubuntu:~/auboData/gittest# git cherry-pick 552e796
error: 不能应用 552e796... feat: brancn2 edit c
提示:冲突解决完毕后,用 'git add <路径>' 或 'git rm <路径>'
提示:对修正后的文件做标记,然后用 'git commit' 提交
可以看出,cherry-pick时,没有成功自动提交,这说明存在冲突,因此首先需要解决冲突,解决冲突后执行git add .,然后执行git commit 或git cherry-pick --continue:
root@ubuntu:~/auboData/gittest# git add .
root@ubuntu:~/auboData/gittest# git commit
branch1 edit c
Conflicts:
c
似乎您正在做一个拣选提交。如果不对,请删除文件
.git/CHERRY_PICK_HEAD
然后重试。
请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交
说明将会终止提交。
日期: Wed Apr 7 10:12:25 2021 +0800
位于分支 branch1
您在执行拣选提交 552e796 的操作。
要提交的变更:
修改: c
修改提交信息后退出编辑器、保存,branch2分支上的最新一次提交成功合入到了branch1分支上。
root@ubuntu:~/auboData/gittest# git log
c434251 - (HEAD -> branch2) feat: branch1 and brancn2 edit c (15 分钟前)
552e796 - feat: brancn2 edit c (28 分钟前)
30f19ec - (origin/master, origin/HEAD, master) feat: add c (3 周前)c3ce9ac - feat: add b (3 周前)
a62306e - feat: add a (3 周前)c28c3a8 - Initial commit (3 周前) <梁龙晓> 将其它分支某次提交合入到本地当前分支,重新编辑提交信息
root@ubuntu:~/auboData/gittest# git cherry-pick -e b244e9
修改提交信息后退出编辑器、保存,branch2分支上的最新一次提交成功合入到了branch1分支上: [branch2 940de17] feat: cherry-pick branch1 add d
Date: Wed Apr 7 10:42:49 2021 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 droot@ubuntu:~/auboData/gittest# git log
940de17 - (HEAD -> branch2) feat: cherry-pick branch1 add d (35 秒钟前)
552e796 - feat: brancn2 edit c (48 分钟前)
30f19ec - (origin/master, origin/HEAD, master) feat: add c (3 周前)c3ce9ac - feat: add b (3 周前)
a62306e - feat: add a (3 周前)c28c3a8 - Initial commit (3 周前) <梁龙晓>
将其它分支所有特有的提交合入到本地当前分支
git cherry-pick ^HEAD [branchname]或git cherry-pick .. [branchname],这些提交是branchname的祖先但不是HEAD的祖先,比如,现在我的仓库中有两个分支,其提交历史如下图:
C<---D<---E branch1
/
master A<---B
\
F<---G<---H branch2
|
HEAD
如果我使用git cherry-pick ..branch1或者git cherry-pick ^HEAD branch1,那么会将属于branch2的祖先但不属于branch3的祖先的所有提交引入到当前分支branch3上,并生成新的提交,执行命令如下:
root@ubuntu:~/auboData/gittest# git cherry-pick ..branch1
[branch2 1ea344e] feat: branch1 add d
Date: Wed Apr 7 10:42:49 2021 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d
[branch2 0b3be14] feat: add f
Date: Wed Apr 7 11:06:04 2021 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 f
[branch2 45ed6tg] feat: branch1 add f
Date: Wed Apr 7 11:08:41 2021 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d
执行后的提交历史如下:
C<---D<---E branch1
/
master A<---B
\
F<---G<---H<---C'<---D'<---E' branch2
|
HEAD
git cherry-pick常见问题
1、The previous cherry-pick is now empty, possibly due to conflict resolution.
原因:
在cherry-pick时出现冲突,解决冲突后本地分支中内容和cherry-pick之前相比没有改变,因此当在以后的步骤中继续git cherry-pick或执行其他命令时,由于此时还处于上次cherry-pick,都会提示该信息,表示可能是由于解决冲突造成上一次cherry-pick内容是空的。
解决方案:
1.执行git cherry-pick --abort取消上次操作。
2.执行git commit --allow-empty,表示允许空提交。
2、fatal: You are in the middle of a cherry-pick – cannot amend.
原因:
在cherry-pick时出现冲突,没有解决冲突就执行git commit --amend命令,从而会提示该信息。
解决方案:
首先在git commit --amend之前解决冲突,并完成这次cherry-pick。
比较文件的不同
比较「暂存区」与「工作区」之间的差异
首先查看仓库状态
root@ubuntu:~/auboData/gittest# git st
位于分支 branch2
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)修改: f
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
从仓库状态可知,此时暂存区为空,此时执行 git diff 指令会将工作区所有已跟踪文件的修改显示出来,现在比较文件不同:
root@ubuntu:~/auboData/gittest# git diff
diff --git a/f b/f
index e69de29..821adb1 100644
--- a/f
+++ b/f
@@ -0,0 +1,2 @@
+branch2
+branch3
此时我们将工作区改动添加至暂存区,再次比较不同:
root@ubuntu:~/auboData/gittest# git add .
root@ubuntu:~/auboData/gittest# git diff
可以看出,没有任何不同,因为工作区已经与暂存区同步了,没有任何不同
比较「暂存区」与「某次提交」之间的差异
上一步操作中,我们已经执行git add .将工作区改动同步到暂存区,此时我们比较暂存区与最新一次提交的不同:
root@ubuntu:~/auboData/gittest# git diff --cached 0b3be1 # 与 git diff --cached HEAD 等价
diff --git a/f b/f
index e69de29..821adb1 100644
--- a/f
+++ b/f
@@ -0,0 +1,2 @@
+branch2
+branch3比较「暂存区」「工作区」与「某次提交」之间的差异
接上一步操作,我们再对文件f添加一行内容,但是不同步至暂存区,比较暂存区、工作区与最新一次提交的不同
root@ubuntu:~/auboData/gittest# git diff 0b3be1 # 与 git diff HEAD 等价
diff --git a/f b/f
index e69de29..76e2936 100644
--- a/f
+++ b/f
@@ -0,0 +1,3 @@
+branch2
+branch3
+branch4
作为对比,我们再次比较暂存区与最新一次提交的不同:
root@ubuntu:~/auboData/gittest# git diff --cached 0b3be1 # 与 git diff --cached HEAD 等价
diff --git a/f b/f
index e69de29..821adb1 100644
--- a/f
+++ b/f
@@ -0,0 +1,2 @@
+branch2
+branch3
比较两个分支上最新提交的内容的差别
我们首先将branch2的修改提交,再比较branch2分支最新提交相对与branch1分支最新提交的不同:
root@ubuntu:~/auboData/gittest# git diff branch1 branch2
diff --git a/f b/f
index e69de29..76e2936 100644
--- a/f
+++ b/f
@@ -0,0 +1,3 @@
+branch2
+branch3
+branch4
交换指令中branch1、branch2位置,则是比较branch1分支最新提交相对与branch2分支最新提交的不同:
root@ubuntu:~/auboData/gittest# git diff branch2 branch1
diff --git a/f b/f
index 76e2936..e69de29 100644
--- a/f
+++ b/f
@@ -1,3 +0,0 @@
-branch2
-branch3
-branch4
生成补丁
git diff [commitId1] [commitId2] > [name].patch是将commitId2的提交相对于commitId1的提交的修改生成名称为[name].patch的补丁文件,特别的,我们将branch1分支最新提交相对与branch2分支最新提交的修改生成名称为1.patch的补丁文件
root@ubuntu:~/auboData/gittest# git diff branch2 branch1 > 1.patch
git format-patch 与git diff的区别在于前者打出来的patch中不带有提交信息
使用补丁
接上文,我们在branch2分支上使用1.patch打补丁
root@ubuntu:~/auboData/gittest# git apply 1.patch
查看仓库状态:
root@ubuntu:~/auboData/gittest# git st
位于分支 branch2
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)修改: f
可以看到patch已经打上去了,但是需要自己提交并写提交信息
生成补丁及打补丁的过程
1、执行命令 git am xxxx.patch 尝试直接打入补丁。因为我们使用的 patch 已经过时了,所以这一步肯定会报错并中断(注意,虽然命令停止执行了,但我们依然处于git am命令的运行环境中,可以通过git status命令查看到当前的状态)。
2、执行命令 git apply --reject xxxx.patch 自动合入 patch 中不冲突的代码改动,同时保留冲突的部分。这些存在冲突的改动内容会被单独存储到目标源文件的相应目录下,以后缀为 .rej 的文件进行保存。比如对 ./test/someDeviceDriver.c 文件中的某些行合入代码改动失败,则会将这些发生冲突的行数及内容都保存在 ./test/someDeviceDriver.c.rej 文件中。我们可以在执行 git am 命令的目录下执行 find -name .rej 命令以查看所有存在冲突的源文件位置。
3、依据 步骤2 中生成的 .rej 文件内容逐个手动解决冲突,然后删除这些 *.rej 文件。完成这一步骤的操作后,我们就可以继续执行 git am 的过程了。
4、执行命令 git status 查看当前改动过的以及新增的文件,确保没有多添加或少添加文件。
5、执行命令 git add . 将所有改动都添加到暂存区(注意,关键字add后有一个小数点 . 作为参数,表示当前路径)。
6、执行命令 git am --resolved 继续 步骤1 中被中断的 patch 合入操作。合入完成后,会有提示信息输出。
7、执行命令 git log 确认合入状态。
git-rebase操作
有几个命令需要注意一下:
pick:正常选中
reword:选中,并且修改提交信息
edit:选中,rebase时会暂停,允许你修改这个commit(参考这里)
squash:选中,会将当前commit与上一个commit合并
fixup:与squash相同,但不会保存当前commit的提交信息
exec:执行其他shell命令
分支合并
1.我们先从 master
分支切出一个开发分支,进行开发:
(master) git checkout -b feature1
2.这时候,你的同事完成了一次 hotfix
,并合并入了 master
分支,此时 master
已经领先于你的 feature1
分支了:
3.恰巧,我们想要同步 master
分支的改动,首先想到了 merge
,执行:
(feature1) git merge master
图中绿色的点就是我们合并之后的结果,执行:
(feature1) git log
就会在记录里发现一些 merge
的信息,但是我们觉得这样污染了 commit
记录,想要保持一份干净的 commit
,怎么办呢?这时候,git rebase
就派上用场了。
4.让我们来试试 git rebase
,先回退到同事 hotfix
后合并 master
的步骤:
5.使用 rebase
后来看看结果:
(feature1) git rebase master
这里补充一点:rebase
做了什么操作呢?
首先,git
会把 feature1
分支里面的每个 commit
取消掉;
其次,把上面的操作临时保存成 patch
文件,存在 .git/rebase
目录下;
然后,把 feature1
分支更新到最新的 master
分支;
最后,把上面保存的 patch
文件应用到 feature1
分支上;
从 commit
记录我们可以看出来,feature1
分支是基于 hotfix
合并后的 master
,自然而然的成为了最领先的分支,而且没有 merge
的 commit
记录,是不是感觉很舒服了。
6.在 rebase
的过程中,也许会出现冲突 conflict
。在这种情况,git
会停止 rebase
并会让你去解决冲突。在解决完冲突后,用 git add
命令去更新这些内容。
注意,你无需执行 git-commit,只要执行 continue
git rebase --continue
这样 git
会继续应用余下的 patch
补丁文件。
7.在任何时候,我们都可以用 --abort
参数来终止 rebase
的行动,并且分支会回到 rebase
开始前的状态。
git rebase —abort
更多 rebase
的使用场景
git-rebase
存在的价值是:对一个分支做「变基」操作。
- 当我们在一个过时的分支上面开发的时候,执行
rebase
以此同步master
分支最新变动; - 假如我们要启动一个放置了很久的并行工作,现在有时间来继续这件事情,很显然这个分支已经落后了。这时候需要在最新的基准上面开始工作,所以
rebase
是最合适的选择。
为什么会是危险操作?
根据上文来看,git-rebase
很完美,解决了我们的两个问题:
- 合并
commit
记录,保持分支整洁; - 相比
merge
来说会减少分支合并的记录;
如果你提交了代码到远程,提交前是这样的:
提交后远程分支变成了这样:
而此时你的同事也在 feature1
上开发,他的分支依然还是:
那么当他 pull
远程 master
的时候,就会有丢失提交纪录。这就是为什么我们经常听到有人说 git rebase
是一个危险命令,因为它改变了历史,我们应该谨慎使用。
除非你可以肯定该 feature1
分支只有你自己使用,否则请谨慎操作。
结论:只要你的分支上需要 rebase
的所有 commits
历史还没有被 push
过,就可以安全地使用 git-rebase
来操作。
参考
rebase
git-rebase 使用总结
git 中的 rebase操作
git-rebase vs git-merge 详解
2. gitlab
# 索引到issue
close #1
2. ssh指令
# 远程登录
ssh
# scp远程拷贝
scp
3. dh_make
# 创建新的debian文件夹
dh_make -s -e louwei@aubo-robotics.cn -n -p libcstone_0.0.1
# 构建
fakeroot debian/rules binary-arch
# 清除
fakeroot debian/rules clean
# 安装
sudo dpkg -i build/*.deb
# 新增发布版本
dch -v x.y.z
# 然后编辑changelog
dch -r
4. gitbook
# 生成文档结构
gitbook init
# 预览
# 首先切换到repo的根目录(README.md所在的目录),然后在浏览器中打开`http://localhost:4000`即可看到相关文档说明
gitbook serve
# 生成html
gitbook build
1. 排版
2. gitbook基本操作
3. 移除GitBook目录下方的“本书使用GitBook发布”字样
4. 生成pdf
5. clang-format
clang-format -i
# 另外clang-format还提供一个clang-format-diff.py脚本,用来格式化patch,code review提交代码前,可以先跑一下这个脚本,看有没有问题。
# 格式化最新的commit,并直接在原文件上修改
git diff -U0 HEAD^ | clang-format-diff.py -i -p1