使用git管理我的项目
目录
1、分支设计
gitee上的远程仓库只给一条main分支,作为可供他人下载的最新版本。
本地的仓库使用git pull和远程的origin/main保持一致,同时每次有改动时新建一个dev分支进行开发,改好后合并到本地的main分支,再git push到远程。之后就可以删掉本地的dev分支了
git branch dev //新建dev分支,但不转到该分支上
git checkout -b dev //新建并转到dev分支
git branch -a //查看所有分支和目前所在分支,包括remote远程上的分支
2、分支切换
本地dev到main分支的切换时,如果dev上进行了修改但是没有git add到暂存区后git commit提交修改,那么这些修改后的文件就会在你切换分支时直接应用到切换后的分支上!
git checkout main //切换到main分支
此时,dev下的修改会被带到main分支里,并且出现以下比较奇怪的标志,如M,T,D,A,R,U等等。
A: 增加的文件.
C: 文件的一个新拷贝.
D: 删除的一个文件.
M: 文件的内容或者mode被修改了.
R: 文件名被修改了。
T: 文件的类型被修改了。
U: 文件没有被合并(你需要完成合并才能进行提交)
X: 未知状态。(很可能是遇到git的bug了,你可以向git提交bug report)
这是因为dev下的修改没有git add 到暂存区,也没有git commit,因此这些文件就没有被纳入git的版本管理系统中,只是一些普通文件。比如被修改的文件就是unstaged状态,新增加的文件就是untracked状态。
解决办法:
1、在切换分支前git stash隐藏该分支下的所有修改,在切换回来后再git stash pop恢复更改。
git status //可以查看此分支里没有被git add和git commit的文件
git stash //在这个dev分支下隐藏所有修改
git checkout main //切换到main分支,去做别的修改
git checkout dev //切换回dev分支
git stash list //List可以查看有哪些commit被隐藏了
git stash pop //恢复所有修改
但stash也不是万能的,根据我的体验,编译后新产生的build、devel文件夹仍然不会被隐藏,会被带入切换后的分支中。
2、在切换分支前git commit所有修改
git add .
git commit -m "your commit message"
这样所有修改都会被纳入版本管理,切换不同的分支时不会有影响。
如果切换分支时忘记了上述操作,dev中没有git add的修改被带进了main分支怎么办呢?
git checkout main //进入main分支
git checkout -- <file_name> //取消单一文件的修改
git checkout . //取消所有文件的修改
3、Tag的使用
git中提倡用tag来标记版本,当然也可以新建release分支来保存版本,但是tag只是一个标签显然更加方便。
tag本身不是分支,只是分支的某一次commit的代号标记。
git tag v1.0.0 //快速在本分支上创建一个标签
git tag -a v1.0.0 -m "tag description" //创建tag和它的说明
git tag //查看所有tag
git show <tag> //查看tag的信息
创建的tag不会随git push 到远程,需要单独push
git push --tag
这样在远程仓库就可以看到这个tag,点进去就是这个tag版本时的代码。在本地也可以切换到这个tag版本的代码:
git checkout <tag>
但是这里会报“HEAD DETACHED",因为tag毕竟不是一个分支,你可以看这个tag时的代码,但是如果要修改,最好还是在这个tag的基础上新建一个分支,再去修改,去merge。
git checkout -a tag_fix //在这个tag版本基础上创建一个新的tag_fix的分支并转到该分支
如果想恢复本地代码到某个tag的版本,可以用git reset。
git show <tag_name> //查看这个tag对应的commit ID(只需要前几位)
git reset <commit_ID> //恢复本分支到这个commit版本
git log // 可以查看本分支历史commit记录
4、使用SSH免密push
如果在添加远程仓库时,用https链接,那么之后每次push都会要求你输入账号密码。
git remote add origin https://gitee.com/xxxxxx.git //添加一个叫origin的远程仓库链接
git clone https://gitee.com/xxxxxx.git //克隆远程仓库
可以使用SSH链接避免每次push都输入密码。
git remote add origin git@gitee.com:xxxxx.git
git clone git@gitee.com:xxxxxx.git
还需要在将本地的ssh公共密钥粘贴到gitee或者github的账号设置里。
本地在~/.ssh文件下下生成.pub的方法(ubuntu):
ssh-keygen
5、子模块更新
如果一个项目里面有子模块submodule(比如px4),那么git clone下来的代码只会有子模块的目录,里面是空的,需要更新。
尤其是切换了分支到某个tag里后,必须要更新下载子模块。
以px4为例,比如从master分支切换到v1.11.3的tag版本分支:
git checkout v1.11.3
git submodule update --init --recursive
自己创建submodule可以参考:
Git--子模块(submodule)介绍_worthsen的博客-CSDN博客_git submodule
git submodule add http://xxx.xxx/common.git
注意:
- submodule是一个单独的子模块,push和pull都要在子模块内进行。
- 子模块push或者pull之后还要在主仓库里commit,因为主仓库只标记submodule的commit id。
- submodule update后子模块处于一个游离的分支(对应主仓库记录的commit id),不要直接在submodule里修改提交,因为这是个游离的分支。而要在子模块自己的仓库里修改,主仓库只pull和update。
6、用gitignore文件忽略某些文件
仓库中的某些文件是不希望加入版本管理并上传到远端仓库的,比如每次编译产生的build和devel文件,常用的方法是在仓库目录下新建一个 .gitignore
文件来忽略这些文件:
/xxx #只忽略本层文件夹下文件名/文件夹名为xxx的文件
xxx #忽略仓库中所有文件名/文件夹名为xxx的文件
xxx* #忽略仓库中所有文件名/文件夹名前含有xxx的文件
*.jpg #忽略仓库中所有后缀为jpg的文件
如
# git ignore the following folders:
/build
/devel
# /logs
# src/CMakeLists.txt
/.catkin_workspace
/.catkin_tools
.vscode
*.egg-info
__pycache__