前言
本学期在学习open source时,和同学一起做项目发现自己对于git和github使用实在是不太清晰,当时只会add, commit, push.但是对于其他操作完全不清晰,在期末后花了四天重新看了一遍git入门资料。进阶的一些功能还是没有学习。更好的git学习应该还是在实践中学习。
学习资料 视频 【GeekHour】一小时Git教程 , *Git 官方文档(推荐)
Key
config,init, clone, status, log, reset, add commit push pull branch, rebase, merge, cherry pick, stash
Distributed Version Control System VS Centralized Version Control System
Centralized: Simplified Management, Easy to learn; Network Dependency, the single point of failure embedded within the centralized server. If the remote server goes down, then no one can work on the code or push changes.:subversion(SVN)
Distributed: 免费开源,速度快,offline。:git Git is a fast distributed revision control system.
git config
git config --global user.name "Meiyu Zhang" #set username
git config --global user.email "lu5558762@gmail.com" #set useremail
git config --get user.name/user.email #查看,少用
git config --global --list #查看信息,多用
创建仓库
git init
git clone
.git是隐藏目录. 使用ls -a查看
工作区域和文件状态
添加和提交文件
git status
git master 和main是因为master会产生歧义,所以之前版本使用master,现在版本使用main,本质上没有区别。
git commit git commit 只会提交暂存区中的文件,不会提交工作区中的其他文件.每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
git add *.txt 'git add .' .代表当前文件夹。 git add . 代表当前文件夹所有文件都添加到暂存区。
git commit -am "message"是add 和 modify俩个命令的合并。可以同时add、modify tracked的文件,如果是新文件,必须使用分开的命令
git log
git log --oneline更简洁的提交 在工作中非常方便,可以更快的找到编码。
git diff
git diff #暂存前后的变化
git diff --cached #查看已经暂存的变化--cashed和--staged是同义词
git diff <#no1> <#no2> #俩个版本之间的变化
git rm
git rm <file> #removes files from the working directory and the staging area.和删除文件后再add . 是一样的
git rm -r * #removes files from the working directory and the staging area. -r represent recursively
git rm --cached README #把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中 eg.忘记添加 .gitignore 文件
#To finalize the deletion, you need to commit the changes
git commit -m "Remove all files and directories"
#如果没有commit changes 可以使用下面命令恢复文件
git checkout --<file>
撤销操作
这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。
# 修改提交
git commit --amend
例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终你只会有一个提交——第二次提交将代替第一次提交的结果。
取消暂存的文件
git reset HEAD <file>
撤销对文件的修改
git checkout -- <file>
请务必记得 git checkout — <file> 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。
记住,在 Git 中任何 已提交 的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复。 然而,任何你未提交的东西丢失后很可能再也找不到了。
面试问题:git push后如何修改?
# 修改最近的一次提交信息
# 1. 修改代码文件,推送到暂存区
git add <file name>
git commit --amend
# 2.强制推送修改后的提交
# 上诉操作会修改提交历史,因此需要强制推送
git push --force origin <branch>
# 修改较早提交 这里没考
git rebase -i HEAD~n ..
注意事项
-
通知团队成员:因为
--force推送会重写历史,可能影响其他团队成员的工作。推送前请与团队成员沟通,确保不会影响他们的工作。 -
备份当前状态:在进行历史重写操作前,建议创建一个临时分支来备份当前状态,以防出现问题:
git checkout -b backup-branch
git reset
- 清除暂存区:
git resetgit reset HEAD file1.txt file2.txt清除added后不想要的内容 - 回滚提交:
git reset <commit>并根据需要选择--soft、--mixed或--hard选项。
回退版本
git reset [mode] <commit>
Soft:
A -- B -- C (HEAD) #initial
git reset --soft HEAD~1 #command
A -- B (HEAD) #result
#Changes from 'C' are kept in the staging area
如果进行了太多次没有意义的commit,则可以使用git reset --soft进行提交合并。
Mixed Staging area matches current HEAD
git reset HEAD example.txt
git reset --hard +commit id #可以恢复到之前的状态。
unstage a file without losing your changes。 Staged but regret.
Hard Staging area m
git reflog 查看操作记录. git reset --hard <版本编号> 更新到之前误操作的操作之前。
git reset的操作多种多样。这里的视频讨论的是如何回滚提交,使用git reset去完成commit的后撤。git reset 还有很多种用法
- 清除暂存区的更改(git add 失误进行撤回)
git reset会将所有的暂存的文件从暂存区移除,但不会更改工作区中的文件。 git reset <commit>这种方式默认使用'--mix' 的选项,工作区更改不变,但取消暂存。
示例
假设你发现最近的一次提交有误,你希望回滚到上一个提交,可以运行:
# 查看提交历史
git log
# 假设你希望回滚到上一个提交
git reset --mixed HEAD~1
# 查看当前状态
git status
如果你只希望清除暂存区的更改,不影响提交历史,可以运行:
# 清除暂存区的所有更改
git reset
Remote Repository
查看远程仓库
git remote # 查看关联的远程仓库
git remote -v #查看关联的所有远程仓库
添加远程仓库
git remote add <shortname> <url> #常用在自己本地已经做好了然后上传到远程上 之后在git push -u origin main
git fetch #从仓库获取最新的提交记录,但不自动合并到你的当前分支
git pull #先从远程仓库获取最新的提交记录,并自动将这些更新合并到你的当前分支
git push <remote> <branch>
现在可以用pb代替整体URL
gitignore
应该忽略哪些文件?
- 系统或软件自动生成的文件
- 编译产生的中间文件和结果文件
- 运行时产生的日志文件(.log)、缓存文件、临时文件
- 涉及身份、密码、口令、秘钥等敏感信息文件
已经被添加到add里的文件 gitignore是没有用的。使用git rm --cached <file>删除。
git 默认不会添加空的文件夹到版本控制中。忽略文件夹 <dir名称>/
.gitignore 文件匹配规则
- 空行或者#开头的行会被git忽略。所以空行用于可读性的分割,#用于注释
- 使用标准的Blob模式匹配,例如: 星号* 通配任意字符 ?匹配单个字符 [] 表示匹配列表中的单个字符, 比如: [abc] 表示a/b/c , [0-9],[a-d], !取反
- ** 表示匹配任意的中间目录
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
Note: 在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore 文件,它递归地应用到整个仓库中。 然而,子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。 (Linux 内核的源码库拥有 206 个 .gitignore 文件。)
VSCode & Git
terminal中 cd 到当前文件夹 code . :在vscode中打开当前文件夹目录。
和git status --short看到的状态是一致的。
git 分支
命名 Branch
在Open Source 这节课看到大家name 自己的branch会是mz_dev, mz_updated_dev 这样的方式。
Example Branch Names
mz_dev: Your development branch.mz_feature_x: A branch for a specific feature you are working on.mz_bugfix_y: A branch for a specific bug fix.
If you're unsure, it's always a good idea to check with your team or project manager to ensure everyone is on the same page regarding branch naming conventions.
git branch #查看所有分支 *<分支名>为当前分支
git branch branch-name #创建分支
git checkout branch-name #转移到该分支 可能会和其他命令重叠 不推荐 但是是官方文档里使用的命令
git switch branch-name #转移到该分支 推荐 新命令
git checkout -a branch-name #创立新branch 并切换到该branch
#Merge全部流程
git checkout master #先切回主分支
git merge branch-name #将该分支合并到主分支内
git log --graph --oneline --decorate --all #图像化查看main和分支的演变过程 万思奇用过
# 分支被合并后不会被删除,仍然存在, 需要手动删除。
git branch -d branch-name #删除已经合并的分支
git branch -D branch-name #强制删除没有合并的分支
gitKaren 的图像化展示和terminal 里用git log --graph --oneline --decorate --all来展示图像化。俩张图的每个点都代表了一个commit.
Once a branch is deleted in Git, it will not longer appear as a separate branch in the branch list of Git clients like GitKraken. However, the commits that were part of the deleted branch are still part of the repository's history. Those commits can still be seen in the GitKraken.
解决分支合并冲突问题
没有冲突,git自动合并。如有冲突,需要手动合并
git status #查看哪里有问题
#你可以打开这些包含冲突的文件然后手动解决冲突
#然后提交
合并 Rebase
可以在任意分支上执行rebase操作。
rebase a : 找到ab的共同祖先,a的HEAD节点做底。
git cherry pick 是什么东西,为什么和release/develop相关
Merge和rebase的区别?何时使用?
Merge: 不会破坏原分支的提交历史,方便回溯和查看。缺点: 会产生额外的提交节点,分支图比较复杂
Rebase: 不会新增额外的提交记录,形成线性历史,干净直观。缺点: 改变提交历史,改变当前分支branch out的节点,避免在同时有同时使用该分支的人时使用rebase命令
总结:都是合并命令,如果一个人:rebase,多个人合作;merge
git工作流程规范
GitFlow模型
git tag 命令只用在主线可以tag版本号。在每次合并分支都建议生成一个新的版本号,方便回溯和追踪。版本号规则: 主版本 Major Version: 主要的功能变化或重大更新;次版本 Minor Version: 一些新功能、改进和更新,通常不会影响现有功能;修订版本 Patch Version: 一些小bug修复,安全漏洞补丁等,不会更改现有功能和接口。
适用于退队水平适中
GithubFlow模型
团队水平较高、开源团队。
Git tag
git tag -a v1.4 -m "my version 1.4" #annotated tag 信息全面
git tag v1.4-lw #lightweight 轻量标签
git show v1.2
git tag -a v1.2 9fceb02 #后期打标签
# !git tag不会自动跟随git push一起被推送到远程仓库,你需要显式的推送标签
# 推送单个标签
git push origin v1.0
#推送多个标签
git push origin --tags
# 删除标签
git tag -d tagname #不会在任何远程仓库删除这个标签
git push <remote> :refs/tags/<tagname> #使用这个更新远程仓库中删除该tag
简化命令
git config --global alias.graph "log --all --graph --decorate --oneline"
git graph = git log --all --graph --decorate --oneline
七七八八
总结: There are multiple ways to remove a file from a commit or the staging area without deleting from working directory. Here are the options.
git rm --cached <file>
git reset --cached <file>
在Git中以单个短横线 - 或双横线 -- 开头的都是参数或选项。这些参数用于修改Git命令的行为。一般来说,单个短横线后面跟一个字母表示短选项(short option),而双横线后面跟的是长选项(long option)
选项和参数的区别:
git [options] [arguments]
Tree
$ tree
.
|____go.mod # dependencies
|____LICENSE
|____ git_functions # Git-Service Server Component
|____Makefile # make test, fmt….
|____README.md
|____.gitignore
|____.circleci # CI configuration
|____main.go # main function
|____pkg # Components
| ├── handler # Server Handler Components
| ├── model # Github-API defined Objects
| └── swagger-ui # Swagger File and Frontend
|____.golangci.yml # golangci-lint Configuration
0. Install the tree: 需要以管理员身份运行powershell 在powershell里choco install tree下载. Chocolatey is a windows package manager软件包管理工具. 和macOS的brew功能一致
- Generate the Working Tree: 直接使用git bash. cd 到你想要生成tree的文件夹,tree一下则生成working tree.
在tree中不太会将文件和文件夹进行分类,在我们学习的这个project里,我们组的组员应该是将不重要的文件名和directory在tree中删掉,只保留重要的文件夹和文件并予以注释。
我的stupid mistakes
原来git commit会显示到github上吗? 我以为比如创建了我的branch 就只会在pull request的时候显示commit。那branch的作用是什么呢?tag的作用又是什么呢?
每次commit就会触发CI/CD的话,那pull request又是在commit的什么时候触发呢?
- git commit 会显示在 GitHub 上,但是只有在你推送 (push) 到 GitHub 仓库之后才会显示。
- CI/CD的触发机制
CI/CD 触发机制
-
本地提交 (
git commit) :- 仅在你的本地仓库中创建一个新的提交记录。
- 不会触发任何 CI/CD 工具,因为这些工具无法访问你的本地提交。
-
推送到远程仓库 (
git push) :- 将本地提交推送到远程仓库(如 GitHub)。
- 远程仓库的变化(如新的提交)会触发 CI/CD 工具(如 CircleCI)的构建和部署流程。
CircleCI 的触发方式
CircleCI 通常会在以下情况被触发:
-
Push 事件:
- 每次将提交推送到远程仓库时,CircleCI 会检测到这些变化并启动相应的构建流程。
-
Pull Request 事件:
- 当创建或更新一个 Pull Request 时,CircleCI 会触发构建和测试,以确保合并前的代码质量。
-
其他事件:
- 根据你的 CircleCI 配置文件(
.circleci/config.yml),可以配置其他触发事件,如发布标签(tag)时的构建等。
- 根据你的 CircleCI 配置文件(
总结
- 本地提交 (
git commit) 不会触发 CI/CD 流程。 - 推送到远程仓库 (
git push) 会触发 CI/CD 流程。 - CircleCI 和其他 CI/CD 工具是基于远程仓库活动触发的,因此仅在本地进行的操作不会触发这些流程。
问题二 如何避免失败的commit
如果你git push你的本地commit时,如果你的代码有问题,那么因为CI/CD的使用,所有人都会看到你这次失败的commit
是的,确实如此。如果你将本地提交推送到远程仓库,并且你的代码有问题,那么 CI/CD 工具(例如 CircleCI)会自动检测到这些问题并运行构建和测试流程。如果这些流程失败,所有有权限访问该仓库的人都会看到这些失败的信息。
如何处理和避免团队、个人代码错误
-
本地测试: 在推送之前,尽量在本地运行所有相关测试,确保代码没有明显的问题。
- 使用命令行工具或集成开发环境(IDE)来运行单元测试、集成测试等。
-
使用分支: 在开发新功能或修复 bug 时,创建一个新的分支进行工作。这样即使推送的代码有问题,也只会影响该分支,而不会影响主分支或其他稳定分支。
- 创建新分支:
git checkout -b feature-branch - 推送分支:
git push origin feature-branch
- 创建新分支:
-
代码审查 (Code Review) : 通过 Pull Request 提交代码,进行代码审查。其他团队成员可以在合并之前查看和评论代码,帮助发现潜在问题。
- 创建 Pull Request 并等待同事审查和批准。
-
配置 CI/CD 触发条件: 在 CI/CD 配置文件中,可以设置触发条件,例如仅在特定分支(如
main或master)上触发完整的构建和部署流程。- 在
.circleci/config.yml文件中设置条件触发。
- 在
总结
通过在本地测试、使用分支、进行代码审查以及配置适当的 CI/CD 触发条件,可以有效地减少将有问题的代码推送到远程仓库的风险,并确保团队协作的代码质量。
其他升级git用法
很有用的功能: git status -suno; git cherry -pick, git reset --hard, git commit -amend; git apply ...
git stash 是什么
Quiz
-
What command can we effectively unstage a file but keep your changes.
git reset HEAD 'file.name' #Primarily used to unstage changes without affecting the working directory. git rm --cached <file> #Used to untrack a file in Git, meaning Git will stop monitoring changes to the file after the removal. #The file remains in the working directory, but future changes to it will not be tracked unless re-added.