Git Standard
-
功能开发分支命名:feature/{taskId}-{infomation}
-
bug 修复分支命名:bugfix/{bugId}-{infomation}
-
提交 log 规范
-
功能开发 log:feature {taskID}:{xxxxxxxxx}
-
bug 提交 log:bugfix {bugId}:{xxxxx}
提交日志规范
# Step 1 $ git log --oneline # Step 2 # 假设往下两个都是当前release的修改 $ git rebase -i head~2 # 第二个合并到前一个,修改第二行的为s,如果有多个合并,保留第一个pick,其余改s # 修改后保存 # Step 3 # 自动弹出commit日志修改,保留自己需要或修改为自己需要的 # 修改后保存 # Step 4 $ git push -f # 使用git log --oneline,提交以及合并
-
-
如果开发后,最新的 release 有修改,需要 rebase 到最新的 release 再测试
-
步骤:切到自己的分支
git checkout release/xxxx git pull --rebase git checkout feature/xxxx git pull –-rebase git rebase origin/release/xxxx # 解决冲突(如果没有冲突,直接跳到最后一步) git add 解决的冲突文件 git rebase --continue # 如果有冲突继续 # 冲突全部解决完毕 git push -f
-
-
如果确定版本稳定,删除修改分支(未强制)
# 现在在task_view_1245分支上,想要删除该分支 $ git checkout master $ git branch -D task_view_1245 # 远程该分支也删除 $ git push origin --delete task_view_1245
分支管理常见命令
$ git branch # 查看当前版本库所有分支
$ git branch <name> # 创建新的分支
$ git checkout <name> or git switch <name> # 切换分支
$ git checkout -b <name> or git switch -c <name> # 创建并切换至新的分支
$ git merge <name> # 将name分支合并至当前分支
$ git log --oneline --graph # 查看具体log信息
$ git branch -d <name> # 删除分支
$ git tag <tag_name> # 为当前的commit创建新的标签
$ git tag -d <tag_name> # 删除标签
Commit Standard
Format of the commit message: #
<type>(<scope>): <subject>
<body>
<footer>
Message: (first line)
First line cannot be longer than 70 characters, second line is always blank and other lines should be wrapped at 80 characters.
Message:
Allowed <type> values:
-
feat: feature 新功能,新需求 (new feature)
-
fix: 修复 bug (bug fix)
-
docs: 仅仅修改了文档,比如 README, CHANGELOG, CONTRIBUTE 等等 (changes to documentation)
-
style: 仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑 (formatting, missing semi colons, etc; no code change)
-
refactor: 代码重构,没有加新功能或者修复 bug (refactoring production code)
-
test: 测试用例,包括单元测试、集成测试等 (adding missing tests, refactoring tests; no production code change)
-
revert: 回滚到上一个版本
-
perf: 性能优化
-
chore: 改变构建流程、或者增加依赖库、工具等,包括打包和发布版本 (updating grunt tasks etc; no production code change)
-
conflict: 解决合并过程中的冲突
Example <scope>
-
init
-
runner
-
watcher
-
config
-
web-server
-
proxy
-
etc...
The <scope> can be empty (eg. if the change is a global or difficult to assign to a single component), in which case the parentheses are omitted.
Message
-
uses the imperative, present tense: “change” not “changed” nor “changes”.
-
includes motivation for the change and contrasts with previous behavior.
For more info about message body, see:
-
https://365git.tumblr.com/post/3308646748/writing-git-commit-messages
-
https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
Message
Closed issues should be listed on a separate line in the footer prefixed with "Closes" keyword like this:
Closes #234
# or in case of multiple issues:
Closes #123, #245, #992
Breaking changes
All breaking changes have to be mentioned in footer with the description of the change, justification and migration notes.
BREAKING CHANGE:
`port-runner` command line option has changed to `runner-port`, so that it is
consistent with the configuration file syntax.
To migrate your project, change all the commands, where you use `--port-runner`
to `--runner-port`.
Commit Example
Capitalized, short (50 chars or less) summary
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, followed by a
single space, with blank lines in between, but conventions vary here
- Use a hanging indent
根据 git commit 自动生成 CHANGELOG.md
https://joyran.github.io/yi-blog/blog/commit-changelog.html
Login & SSH
Generate SSH Key by ssh-keygen
usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]
[-m format] [-N new_passphrase] [-O option]
[-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]
[-w provider] [-Z cipher]
Debug
Permission Denied
if the following error occur
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Solution
$ ssh-keygen -t rsa -C hongfeiniu1@gmail.com
$ ssh-add ~/.ssh/id_rsa # add ssh key to ssh-agent
Open Connection Failed
Could not open a connection to your authentication agent.
- Lint the ssh-agent
# linux
$ eval "$(ssh-agent -s)" # option 1
$ eval "ssh-agent" # option 2
# windows
PS D:\code> get-service ssh*
PS D:\code> Set-Service -Name ssh-agent -StartupType Manual
PS D:\code> Start-Service ssh-agent
# 查看ssh-add添加成功
PS D:\code> ssh-add -l
Status Name DisplayName
------ ---- -----------
Stopped ssh-agent OpenSSH Authentication Agent
- Copying the Public Key to the Server(未尝试)
$ ssh-copy-id -i ~/.ssh/tatu-key-ecdsa user@host
$ ssh -vT git@github.com # auth the key
Host key verification failed
A 通过 ssh 登陆 B 时提示 Host key verification failed.
A 的 known_hosts 文件中记录的 B 的公钥 1 与 连接时 B 传过来的公钥 2 不匹配。
A 通过 ssh 首次连接到 B,B 会将公钥 1(host key)传递给 A,A 将公钥 1 存入 known_hosts 文件中,以后 A 再连接 B 时,B 依然会传递给 A 一个公钥 2,OpenSSH 会核对公钥,通过对比公钥 1 与公钥 2 是否相同来进行简单的验证,如果公钥不同,OpenSSH 会发出警告, 避免你受到 DNS Hijack 之类的攻击。。
known_hosts 字符串格式:ip 公钥
192.168.44.241 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCHtSvSwuK5F32cxU+5zYtZ/EzHPAO5rTvKgvqldLLKp8sM8uB2RivcZT+U+kcl38F73qRK7iGmUUq7ZXMJE0ag=
Solution
-
方法一:删除 A 的 known_hosts 文件中记录的 B 的公钥(手动进行,不适用于自动化部署情形)
-
方法二:修改配置文件,在 ssh 登陆时不通过 known_hosts 文件进行验证(安全性有所降低),修改完需重启机器
$ vi ~/.ssh/config #编辑配置文件 # 添加以下两行内容: StrictHostKeyChecking no UserKnownHostsFile /dev/null $ ssh-keygen -R 你要访问的IP地址 #update the ssh key? ***测试*** -
Change the Connection to SSH
$ git remote set-url origin git@github.com:Hongfei-Niu/Note.git
# for Windows
$ git remote set-url origin https://github.com:Hongfei-Niu/Note.git
- Merge the Branch
$ git config pull.rebase false
Git New Repository Config
Git global setup
git config --global user.name "牛鸿飞"
git config --global user.email "niuhongfei@wuzhi-ai.com"
Create a new repository
git clone git@gitlab.wuzhi-ai.com:niuhongfei/playbook_standardization.git
cd playbook_standardization
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
Push an existing folder
cd existing_folder
git init
git remote add origin git@gitlab.wuzhi-ai.com:niuhongfei/playbook_standardization.git
git add .
git commit -m "Initial commit"
git push -u origin master
Push an existing Git repository
cd existing_repo
git remote rename origin old-origin
git remote add origin git@gitlab.wuzhi-ai.com:niuhongfei/playbook_standardization.git
git push -u origin --all
git push -u origin --tags
Process the file name and folder
- modify the filename
git mv old_filename new_filename
- create new folder
git add folder
commit
追加代码修改内容
如果我们不小心提交了一版我们不满意的代码,并且给它推送到服务器了,在代码没被 merge 之前我们希望再修改一版满意的,而如果我们不想在服务器上 abondon,那么我们怎么做呢?
追加提交,它可以在不增加一个新的 commit-id 的情况下将新修改的代码追加到前一次的 commit-id 中
$ git commit --amend
如果 master 发生变动:
- 使用 git log 来查看版本库中的之前的 commit-id
- 在终端中执行 git reset --hard commit-id,
- 运行 git log -1 最近的一版就是我们需要的那版,此时再在工作区直接修改代码,改完之后进行 git add,再执行本 git commit --amend 命令,之后 git push.
Diff
当前的工作区和上一次 commit 的版本库
$ git diff
当前的暂存区和上一个 commit
$ git diff --cached
当前暂且区和工作区
$ git diff HEAD
不同分支的文件的文件
$ git diff <branchA> <branchB> <filePath>
.gitignore
make gitignore effect
# 注意有个点“.”
git rm -r --cached .
git add -A
git commit -m "chore<.gitignore>: update .gitignore"
.gitignore grammer
补充一下 .gitignore 的匹配规则:
#以此开头的行为注释行
.a #过滤所有 .a 结尾的文件
/a/ #过滤根目录下的 a 文件夹下的所有文件
/a/do.c #过滤指定文件 /a/do.c
!lib.a #从过滤的文件中排除 lib.a
!/a/b #从过滤的文件中排除 根目录下a目录下的b文件
!.c #从过滤的文件中排除所有.c文件
/TODO #仅仅过滤项目根目录下的 TODO 文件,不包括subdir/TODO
build/ #过滤 build/目录下的所有文件
# * 用来匹配零个或多个字符,如*.[oa]忽略所有以".o"或".a"结尾,*~忽略所有以~结尾的文件(这种文件通常被许多编辑器标记为临时文件);
# [] 用来匹配括号内的任一字符,如[abc],也可以在括号内加连接符,如[0-9]匹配0至9的数;
# ? 用来匹配单个字符。
doc/*.txt #过滤doc下所有txt文件,但不包括子目录下的txt文件,如doc/server/arch.txt
doc/**/*.txt # 会忽略掉 doc/ 里面所有的txt文件,包括子目录下的(**/ 从 Git 1.8.2 之后开始支持 **/ 匹配模式,表示递归匹配子目录下的文件)
调试.gitignore 文件
有时候,确定为什么要忽略特定文件可能会很困难,尤其是当您使用多个.gitignore 文件或复杂格式时。这是 git check-ignore 命令的用处,告诉 git 显示匹配模式的详细信息。
例如,要检查为什么忽略 www/yarn.lock 文件,可以运行:
git check-ignore -v www/yarn.lock
# 输出显示gitignore文件的路径,匹配行的编号和实际模式。
www/.gitignore:31:/yarn.lock www/yarn.lock
该命令还接受多个文件名作为参数,并且文件不必存在于您的工作树中。
显示所有被忽略的文件
带有--ignored 选项的 git status 命令显示所有被忽略文件的列表:
git status --ignored
Stash 暂存区
当需要拉取远端文件,但又不想提交正在修改的文件时,可以使用 git stash 命令将当前的工作区保存(藏匿)起来,等 pull 完后再还原。
此功能类似于实现了 ‘局部拉取更新’ 。
命令如下:
git stash //暂存修改工作区
git pull //拉取远端文件
git stash list
git stash pop stash@{0} //将工作区还原
注:如果还原工作区的文件与 pull 下来的文件有冲突,要手动修改冲突
git stash pop
- 切换分支时,如果当前分支有修改,又不想提交或放弃,可以使用 git stash 将改动存到暂存区。
- git stash 后即可以随意切换分支,切换后再使用 git stash pop 即可将暂存区的改动恢复至当前分支。
但如果使用 git stash pop 后有冲突时,如何撤销?
- 可以使用 git reset --hard ,即可撤销 git stash pop 操作,将当前分支状态恢复。
- 而该操作后,git stash 暂存区的记录也不会被删除,可通过 git stash show 查看。
Merge Fork
Git remote -v
Git remote add upstream <git link>
Git remote -v
Git fetch upstream
Git checkout master
Git merge upstream/master
Git push origin master
Reset, Rebase & Revert
本地或者自己单独的仓库使用 reset 或者 revert 都可以
涉及到远程仓库(公用仓库)时,不要使用 reset,而使用 revert 回滚
git revert
git revert 撤销某次操作
-
此次操作之前和之后的 commit 和 history 都会保留
-
并且把这次撤销作为一次最新的提交
git revert [--[no-]edit] [-n] [-m parent-number] [-s] [-S[]] …
--edit or --no-edit 是否弹出 commit message 窗口
**-n **是 --no-commit 的缩写
-m parent-number 存在 merge 是,指定父系分支号?这个还不怎么懂,暂时略过。
假设 master 分支上的提交记录如下:
A->B->C->D
目前 HEAD 指向 commit D,我们要将代码 revert 到 B 提交时的状态
{: id="20230625104207-e2zcv2h" updated="20230625104207"}
# Method 1
{: id="20230625104207-a1d1wns" updated="20230625104207"}
$ git revert C D # 会生成2个新的commit分别覆盖C、D的提交
{: id="20230625104207-nyhgdnl" updated="20230625104207"}
# Method 2
{: id="20230625104207-7ctxqm0" updated="20230625104207"}
$ git revert -n C D # 不会生成新的提交,但是回滚变动会作为修改变动添加到了索引区,可以直接调用git commit保存或者git revert --conitnue弹出commit页面
{: id="20230625104207-iw10dob" updated="20230625104207"}
# Method 3
{: id="20230625104207-ctch65z" updated="20230625104207"}
$ git revert -n C..D
{: id="20230625104207-36qsjbp" updated="20230625104207"}
$ git revert C..D # 类似方法1,revert从C到D之间的提交,假设中间还有很多提交时可以用这种
{: id="20230625104207-r76rvsx" updated="20230625104207"}
其他操作
{: id="20230625104207-mvqhgrm" updated="20230625104207"}
$ git revert HEAD # 撤销前一次 commit
{: id="20230625104207-muh3zhu" updated="20230625104207"}
$ git revert HEAD^ # 撤销前前一次 commit
{: id="20230625104207-8djyai2" updated="20230625104207"}
$ git revert HEAD~10 # 将head指向上10次的commit。
{: id="20230625104207-9ex9n1q" updated="20230625104207"}
$ git revert <commit id> #(比如:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)撤销指定的版本,撤销也会作为一次提交进行保存。
{: id="20230625104207-1de56h2" updated="20230625104207"}
git revert 是提交一个新的版本,将需要 revert 的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容
git reset
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] []
参数可以选择:
-
hard :当使用这个命令后,工作区、暂存区的内容都会和当前 head 指向的内容相同。
-
直接把 HEAD 指针移动到 commit ID 上,无论修改是否被 add 、 commit ,都直接重置(此时暂存区被清空,工作区的修改被清空),所做的修改将全部丢失,这是非常危险的;
-
但是如果你修改之后进行了 commit 操作,那非常好办,可以用 reflog 查询相应的 hash 值,进行恢复;
- git reflog 和 git log 很像,git 不会显示已删除的 commit 记录(reset 操作导致或者其它操作),但是 git reflog 会显示,然后在重新使用 git reset 命令;
-
如果你修改之后,进行了 add 操作,也可以恢复,但是比较麻烦,用 git fsck --lost-found
-
-
soft: 当使用这个这个命令后,head 指针指向指定的 commit,但是工作区、暂存区的内容不会发生变化。
-
mixed: 暂存区的内容将会发生变化,但是工作区的内容不会发生变化。
假设 master 分支上的提交记录如下:
A->B->C->D
目前 HEAD 指向 commit D,我们要将代码回退到 B 提交时的状态
{: id="20230625104207-5qix83z" updated="20230625104207"}
# 方法1
{: id="20230625104207-2dayrfv" updated="20230625104207"}
$ git reset --soft B # 这个时候可以发现,C,D两次提交做的修改依然存在,并且在索引区内,这个时候如果直接调用git commit ,可以生成一个新的提交E,E包含C、D两次提 交的修改。
{: id="20230625104207-dwx7rhr" updated="20230625104207"}
# 方法2
{: id="20230625104207-x95pnyk" updated="20230625104207"}
$ git reset --mixed B # 二者是一样的
{: id="20230625104207-5e1ion6" updated="20230625104207"}
$ git reset B # 这个时候可以发现,C,D两次提交做的修改依然存在,但是不在索引区内,记如果需要重新提交,则需要先调用git add。
{: id="20230625104207-q0gjfbc" updated="20230625104207"}
# 方法3
{: id="20230625104207-9x0vjew" updated="20230625104207"}
$ git reset --hard B # 和--soft、--mixed不同的是,C,D两次提交做的修改以及D以后做的一些没有提交的修改都不复存在
{: id="20230625104207-o5v9q6n" updated="20230625104207"}
--merge说明
{: id="20230625104207-of9wamt" updated="20230625104207"}
这个参数使用的有一定的前提,需要保证没有添加到索引区的修改文件在新旧两个HEAD直接的提交中没有过修改。如果下面命令调用成功
{: id="20230625104207-25kty7d" updated="20230625104207"}
$ git reset --merge B
{: id="20230625104207-ku2f4kf" updated="20230625104207"}
则会保留没有添加到索引区的修改。即,假设commit C 和 commit D都只修改了a.txt,而在D后我们又修改了b.txt,但是没有调用git add b.txt保存修改到索引区,则调用git reset --merge B 成功后,原来对b.txt做的修改还会存在,但是C、D提交中的修改将会回滚消失
{: id="20230625104207-k4bpa6p" updated="20230625104207"}
--keep说明
{: id="20230625104207-i66rutf" updated="20230625104207"}
和--merge有一些类似。使用成功的前提是:在D后有本地修改的文件在C、D两次提交中没有修改过,即C、D两次提交中没有它的修改记录。
{: id="20230625104207-vaz2bgg" updated="20230625104207"}
假设我们在D后修改了a.txt文件,而且C、D两次提交中我们都没有修改a.txt文件,这样我们调用
{: id="20230625104207-1qwm25r" updated="20230625104207"}
git reset --keep B
{: id="20230625104207-eej3mup" updated="20230625104207"}
可以成功,并且a.txt文件中的修改依然会保留。
{: id="20230625104207-txsu855" updated="20230625104207"}
git rebase
说明:变基操作。
场景 1:本地有多个 commit,想合并成一个 commit。
假设如下:
master 分支提交历史为:A->B->C->D
你后面发现 commit C 和 D 有些问题,需要做一些变动,比如
- 将 C、D 两次提交合并成一次提交 squash D //将 D 合并到 C 提交 或者用 fixup D,但是这样会丢弃 D 的提交 message
- 删除 D 提交 drop D //删除 D
- 修改 D 提交的 message reword D//修改 D 提交的 message,等等。
则可以调用
git rebase -i B
然后会弹出编辑窗口,相应的做修改即可。也就是变更修改 pick、reword、squash、fixup、drop 等命令。
{: id="20230625104207-7z944jf" updated="20230625104207"}
pick:保留这份commit。
{: id="20230625104207-vcprpsl" updated="20230625104207"}
reword: 保留这份commit,但是会重新编辑commit信息
{: id="20230625104207-omx3ykh" updated="20230625104207"}
squash : 这份commit的内容虽然会保留,但是会合并到先前的commit中。
{: id="20230625104207-vixmokz" updated="20230625104207"}
drop: 移除这份commit的内容
{: id="20230625104207-osyje2q" updated="20230625104207"}
等等
{: id="20230625104207-2tf9qve" updated="20230625104207"}
场景 2:整合分支
假设 origin/master 分支上的提交历史为 A->B->C->D;
- 你在本地新添加了一个提交 E,则 master 为 A->B->C->D->E。
- 此时队友新推送一个提交 N 到 origin/master,则 origin/master 分支上提交历史为 A->B->C->D->N。
- 如果你在本地采用 merge 的方式,则提交历史会在分叉变成 A->B->C-D->(E,N)->M(表示 Merge 后的新提交)。
而才有 rebase 方式的话
{: id="20230625104207-66be7b2" updated="20230625104207"}
$ git fetch origin master # 更新代码
{: id="20230625104207-9fu81u5" updated="20230625104207"}
$ git rebase origin/master # 变基操作
{: id="20230625104207-p9uamk2" updated="20230625104207"}
# 则本地master提交历史可能变成A->B->C->D->N->E不会存在分叉。
{: id="20230625104207-1c3vct4" updated="20230625104207"}
场景 3:将某一段 commit 粘贴到另一个分支上
假设如下:
- master 分支提交历史为:A->B->C
- server 分支提交历史为:A->B->D->E
- client 分支提交历史为:A->B->D->F
{: id="20230625104207-6rvzt4r" updated="20230625104207"}
$ git rebase [startpoint] [endpoint] --onto [branchName] # 将当前分支的commits 放到目标分支,HEAD anchor还在原先的commit上
{: id="20230625104207-fuy4n6p" updated="20230625104207"}
$ git checkout <branchName>
{: id="20230625104207-fslfrz8" updated="20230625104207"}
$ git reset --hard <new commit id> # 并把HEAD anchor移到最新的commit上
{: id="20230625104207-2okob0i" updated="20230625104207"}
# 新花样
{: id="20230625104207-8n9t8ug" updated="20230625104207"}
$ git rebase --onto master server client
{: id="20230625104207-q6f6kys" updated="20230625104207"}
这样会取出 client 分支,找出处于 client 分支和 server 分支的共同祖先之后的修改,然后把他们在 master 分支上重演一遍
这样 client 分支会变成 A->B->C->F,注意 server 和 client 共同拥有的 D 提交记录在 client 里消失了
场景 4: 同步远程分支
git pull --rebase
- git pull = git fetch && git merge
- git pull --rebase = git fetch && git rebase
完整流程
{: id="20230625104207-ocqr3y6" updated="20230625104207"}
$ git rebase --continue
{: id="20230625104207-331fd40" updated="20230625104207"}
# 如果有冲突, 解决冲突
{: id="20230625104207-nrkdm3c" updated="20230625104207"}
# after solving the conflicts
{: id="20230625104207-c06woru" updated="20230625104207"}
$ git add .
{: id="20230625104207-ojkmvqp" updated="20230625104207"}
# 不需要commit
{: id="20230625104207-er6g7gd" updated="20230625104207"}
$ git rebase --continue
{: id="20230625104207-kf4sh50" updated="20230625104207"}
$ git push
{: id="20230625104207-sqvhb1m" updated="20230625104207"}
Explanation 1
To be specific, it equals to:
{: id="20230625104207-gpzh0sw" updated="20230625104207"}
$ git fetch origin
{: id="20230625104207-gii4dpn" updated="20230625104207"}
$ git rebase --onto origin/foo e(middle commit) foo
{: id="20230625104207-00y417e" updated="20230625104207"}
Explanation 2
Suppose you have two commits in local branch:
{: id="20230625104207-52hu2oq" updated="20230625104207"}
D---E master
{: id="20230625104207-thq3928" updated="20230625104207"}
/
{: id="20230625104207-cbs6qfr" updated="20230625104207"}
A---B---C---F origin/master
{: id="20230625104207-lub89cc" updated="20230625104207"}
After "git pull", will be:
{: id="20230625104207-s85lmmg" updated="20230625104207"}
D--------E
{: id="20230625104207-gbkcwvb" updated="20230625104207"}
/ \
{: id="20230625104207-nfte9xz" updated="20230625104207"}
A---B---C---F----G master, origin/master
{: id="20230625104207-xo1smn5" updated="20230625104207"}
After "git pull --rebase", there will be no merge point G. Note that D and E become different commits:
{: id="20230625104207-dzn2i2w" updated="20230625104207"}
A---B---C---F---D'---E' master, origin/master
{: id="20230625104207-u5fgqya" updated="20230625104207"}
修改分支名称
rename branch
Step 1. 本地分支重命名(还没有推送到远程)
{: id="20230625104207-g3s8m8s" updated="20230625104207"}
git branch -m oldName newName
{: id="20230625104207-ebfqb6t" updated="20230625104207"}
Step 2. 远程分支重命名 (已经推送远程-假设本地分支和远程对应分支名称相同)
{: id="20230625104207-rgfyj2d" updated="20230625104207"}
# a. 重命名远程分支对应的本地分支
{: id="20230625104207-9ozgbsd" updated="20230625104207"}
git branch -m oldName newName
{: id="20230625104207-kuf2itz" updated="20230625104207"}
# b. 删除远程分支
{: id="20230625104207-u4vizxt" updated="20230625104207"}
git push --delete origin oldName
{: id="20230625104207-cv9r6xh" updated="20230625104207"}
# c. 上传新命名的本地分支
{: id="20230625104207-hbh7vgn" updated="20230625104207"}
git push origin newName
{: id="20230625104207-fl7hom8" updated="20230625104207"}
# d.把修改后的本地分支与远程分支关联
{: id="20230625104207-itl8oyb" updated="20230625104207"}
git branch --set-upstream-to origin/newName
{: id="20230625104207-dwvwovu" updated="20230625104207"}
恢复分支(远程)
Recover the remote branch
思路:找到分支 id,本地重新创建该分支,推送到远程
Step 1: 找到分支 commitId
{: id="20230625104207-94ryt3r" updated="20230625104207"}
很多种方法
{: id="20230625104207-epf0zoo" updated="20230625104207"}
git reflog
{: id="20230625104207-kplsxpe" updated="20230625104207"}
git log
{: id="20230625104207-zzdil73" updated="20230625104207"}
或者gitlab or github界面Project Activity里找到操作ID
{: id="20230625104207-y4ta3g9" updated="20230625104207"}
Step 2: 本地重新创建分支,推送到远程
-
git branch recovery_
-
git branch -m recovery_ # 可忽略,保存个备份挺好
-
git push --set-upstream origin recovery_
问题场景
已经删除了远程分支,但本地环境仍能看到远程分支
{: id="20230625104207-2lwz4vc" updated="20230625104207"}
git remote show origin
{: id="20230625104207-2qulacs" updated="20230625104207"}
# 使用下述命令在本地删除远程不存在的分支
{: id="20230625104207-izbp5r8" updated="20230625104207"}
git remote prune origin
{: id="20230625104207-qvk5haf" updated="20230625104207"}
git 拉取远程分支并创建本地分支
- 查看远程分支
{: id="20230625104207-bhja9yj" updated="20230625104207"}
git branch -r
{: id="20230625104207-4qczhag" updated="20230625104207"}
- 拉取远程分支并创建本地分支
采用此种方法建立的本地分支会和远程分支建立映射关系。
{: id="20230625104207-kshcyeo" updated="20230625104207"}
git checkout -b 本地分支名x origin/远程分支名x
{: id="20230625104207-kng3xj1" updated="20230625104207"}
从其他分支 merge 个别文件或文件夹
- Method 1: 强制合并
{: id="20230625104207-m4b71wj" updated="20230625104207"}
$ git branch
{: id="20230625104207-9yyxn73" updated="20230625104207"}
* A
{: id="20230625104207-pj1l0rc" updated="20230625104207"}
B
{: id="20230625104207-lpc75fw" updated="20230625104207"}
$ git checkout B message.html message.css message.js other.js
{: id="20230625104207-pfyci9c" updated="20230625104207"}
$ git status
{: id="20230625104207-li9sbgv" updated="20230625104207"}
# On branch A
{: id="20230625104207-wiq9b6j" updated="20230625104207"}
# Changes to be committed:
{: id="20230625104207-t66188m" updated="20230625104207"}
# (use "git reset HEAD <file>..." to unstage)
{: id="20230625104207-hvgdudw" updated="20230625104207"}
#
{: id="20230625104207-csxmlhs" updated="20230625104207"}
# new file: message.css
{: id="20230625104207-mr4kcud" updated="20230625104207"}
# new file: message.html
{: id="20230625104207-oo2wpnl" updated="20230625104207"}
# new file: message.js
{: id="20230625104207-mx2za9q" updated="20230625104207"}
# modified: other.js
{: id="20230625104207-ac6ijnd" updated="20230625104207"}
#
{: id="20230625104207-awn83nz" updated="20230625104207"}
- Method 2: 智能合并
- 新建 A_temp 分支,以防万一
{: id="20230625104207-fd81uly" updated="20230625104207"}
$ git checkout -b A_temp
{: id="20230625104207-f5u6gul" updated="20230625104207"}
Switched to a new branch 'A_temp'
{: id="20230625104207-n6h00hl" updated="20230625104207"}
- 合并 B 到 A_temp 分支
{: id="20230625104207-r9kn09j" updated="20230625104207"}
$ git merge B
{: id="20230625104207-xq0uwa5" updated="20230625104207"}
Updating 1f73596..04627b5
{: id="20230625104207-9yiqn2b" updated="20230625104207"}
Fast-forward
{: id="20230625104207-80p273t" updated="20230625104207"}
message.css | 0
{: id="20230625104207-l0mvrco" updated="20230625104207"}
message.html | 0
{: id="20230625104207-3abn7du" updated="20230625104207"}
message.js | 0
{: id="20230625104207-j7jrd6y" updated="20230625104207"}
other.js | 1 +
{: id="20230625104207-0k4p899" updated="20230625104207"}
4 files changed, 1 insertion(+)
{: id="20230625104207-7rezwn1" updated="20230625104207"}
create mode 100644 message.css
{: id="20230625104207-y1qk1e0" updated="20230625104207"}
create mode 100644 message.html
{: id="20230625104207-5ux8yyr" updated="20230625104207"}
create mode 100644 message.js
{: id="20230625104207-s8x90k8" updated="20230625104207"}
- 切换到 A 分支,并使用 git checkout 将 A_temp 分支上的系统消息功能相关文件或文件夹覆盖到 A 分支
{: id="20230625104207-8xqc5rl" updated="20230625104207"}
$ git checkout A
{: id="20230625104207-bfjhj85" updated="20230625104207"}
Switched to branch 'A'
{: id="20230625104207-526jblz" updated="20230625104207"}
$ git checkout A_temp message.html message.css message.js other.js
{: id="20230625104207-mso6v7z" updated="20230625104207"}
$ git status
{: id="20230625104207-rnj1fgq" updated="20230625104207"}
# On branch A
{: id="20230625104207-l487fhj" updated="20230625104207"}
# Changes to be committed:
{: id="20230625104207-fef0x9g" updated="20230625104207"}
# (use "git reset HEAD <file>..." to unstage)
{: id="20230625104207-jklgdvh" updated="20230625104207"}
#
{: id="20230625104207-cpt9859" updated="20230625104207"}
# new file: message.css
{: id="20230625104207-uppr6z4" updated="20230625104207"}
# new file: message.html
{: id="20230625104207-2vgp4v4" updated="20230625104207"}
# new file: message.js
{: id="20230625104207-ybw4ssd" updated="20230625104207"}
# modified: other.js
{: id="20230625104207-vzl43ik" updated="20230625104207"}
#
{: id="20230625104207-06slvi3" updated="20230625104207"}
Tools
gh-md-toc
生成 READ.md 的目录: gh-md-toc or "Markdown All in One" Plugin in VSCode
gh-md-toc will automatically be available in the PATH
Installation
- Linux (manual installation)
{: id="20230625104207-30ikooo" updated="20230625104207"}
$ wget https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc
{: id="20230625104207-8jt0bjg" updated="20230625104207"}
$ chmod a+x gh-md-toc
{: id="20230625104207-se7f5yd" updated="20230625104207"}
- MacOS (manual installation)
{: id="20230625104207-rcdqtqa" updated="20230625104207"}
$ curl https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc -o gh-md-toc
{: id="20230625104207-4dh8bgf" updated="20230625104207"}
$ chmod a+x gh-md-toc
{: id="20230625104207-6e5z66l" updated="20230625104207"}
- Linux or MacOS (using Basher)
{: id="20230625104207-p69hb33" updated="20230625104207"}
$ basher install ekalinin/github-markdown-toc
{: id="20230625104207-8ce16lu" updated="20230625104207"}
Example
STDIN
Here's an example of TOC creating for markdown from STDIN:
{: id="20230625104207-tnr3u18" updated="20230625104207"}
$ cat ~/projects/Dockerfile.vim/README.md | ./gh-md-toc -
{: id="20230625104207-4hy3ilh" updated="20230625104207"}
Local files
Here's an example of TOC creating for a local README.md:
{: id="20230625104207-ew7q6o8" updated="20230625104207"}
$ ./gh-md-toc ~/projects/Dockerfile.vim/README.md
{: id="20230625104207-cunpxqj" updated="20230625104207"}
Debug
divergent branches and reconcile
{: id="20230625104207-u7767n0" updated="20230625104207"}
hint: You have divergent branches and need to specify how to reconcile them.
{: id="20230625104207-hos9v8y" updated="20230625104207"}
hint: You can do so by running one of the following commands sometime before
{: id="20230625104207-019kmut" updated="20230625104207"}
hint: your next pull:
{: id="20230625104207-g5usg4s" updated="20230625104207"}
hint:
{: id="20230625104207-hl3egvi" updated="20230625104207"}
hint: git config pull.rebase false # merge (the default strategy)
{: id="20230625104207-wufoh65" updated="20230625104207"}
hint: git config pull.rebase true # rebase
{: id="20230625104207-6kiqzlp" updated="20230625104207"}
hint: git config pull.ff only # fast-forward only
{: id="20230625104207-yma4tzb" updated="20230625104207"}
hint:
{: id="20230625104207-6sqbb08" updated="20230625104207"}
hint: You can replace "git config" with "git config --global" to set a default
{: id="20230625104207-azvemx3" updated="20230625104207"}
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
{: id="20230625104207-nu0f2nu" updated="20230625104207"}
hint: or --ff-only on the command line to override the configured default per
{: id="20230625104207-qipke0g" updated="20230625104207"}
hint: invocation.
{: id="20230625104207-wesyeng" updated="20230625104207"}
known host problem
When the ip is changed and relevant host get clean, the password would pop up as: "git@github.com's password: ". May caused by ssh.
研究一下 github 验证机制
(Git TroubleShooting)[https://docs.github.com/en/authentication/troubleshooting-ssh/error-permission-denied-publickey]
git case insensitive
Git 大小写不敏感,修改目录名大小写失败
{: id="20230625104207-ghlf6nl" updated="20230625104207"}
$ git config core.ignorecase false
{: id="20230625104207-z0kc751" updated="20230625104207"}
Solution
- 文件夹备份
- git config core.ignorecase false 设置大小写敏感
- cd... 进入到文件夹目录下,我的文件夹名是 Container,执行命令删除:git rm Container
- 将备份文件夹重命名大小写放回原来路径下
- 执行命令添加:git add container
- 查看状态:git status
- 提交:git commit -m '文件夹大小写'
- 推到远程分支:git push origin 本地分支名:远程分支名,远程分支若不存在会自动创建 git push origin base_portal_mysql_wanghongfa:base_portal_mysql_wanghongfa
mv to rename
Cause
{: id="20230625104207-b7f82s3" updated="20230625104207"}
git mv CyberSecurity/password.md CyberSecurity/ldap.md
{: id="20230625104207-bienp4z" updated="20230625104207"}
Error
{: id="20230625104207-jvxlii8" updated="20230625104207"}
fatal: not under version control, source=CyberSecurity/password.md, destination=CyberSecurity/ldap.md
{: id="20230625104207-dea1k1x" updated="20230625104207"}
-
Solution1
Most easiest way to solve this issue is to first we need to add the file first and then we need to rename the file
$ git add file-name $ git mv current-file-name new-file-nameand then your problem will be solve.
-
Solution2
Caused by Case Sensitive difference between Git and Windows Shell
Another quirk that left me frustrated is if you're using the command line, it will use your current path to git mv the file. So if you have a file in C:\Git\MyRepo\MyFolder\MyFile.txt
If you do:
c: cd git cd myrepo cd myfolder dirIt will work fine, you'll see your file. But if you type git mv MyFile.txt MyFile2.txt you will get an error because git can't find Myfile.txt.
The reason is that it's looking at your current path, which is c:\git\myrepo\myfolder\
But git is case sensitive. So you have to go back and type
c: cd Git cd MyRepo cd MyFolderIf you then type git mv it will work fine.
Putting this in as an answer for people like me that found this post while debugging this error message.
-
fatal: unable to access The requested URL returned error: 403
{: id="20230625104207-i1lu6pa" updated="20230625104207"}
edit .git/config
{: id="20230625104207-ok6aaub" updated="20230625104207"}
! [remote rejected] master -> master (pre-receive hook declined)
git push 不上去的原因在于所 push 的分支权限为 protected,只有项目的管理员或者项目的管理员指派的具有相应权限的人才能进行 push,要进行项目的 push,有如下两种方法:
1.将所要 push 的内容所在的分支的 protected 权限关闭
- 进入所在项目的 settings
- 点击进入 Protected branches,点击 unprotected 将 master 分支的权限改变,即关闭 master 的 protected 权限
2.新建其它分支,将项目 push 到新建的分支上,后期再进行 merge
{: id="20230625104207-c6zhhzx" updated="20230625104207"}
# 新建分支
{: id="20230625104207-voap4ni" updated="20230625104207"}
git branch feature
{: id="20230625104207-o4wpy89" updated="20230625104207"}
# 切换分支
{: id="20230625104207-vksnqs7" updated="20230625104207"}
git checkout 分支名
{: id="20230625104207-urjtn80" updated="20230625104207"}
# 进行项目上传
{: id="20230625104207-844cafr" updated="20230625104207"}
git add .
{: id="20230625104207-x3qsoco" updated="20230625104207"}
git commit -m "提交的信息"
{: id="20230625104207-e90gmmk" updated="20230625104207"}
git remote add origin 远程仓库地址
{: id="20230625104207-ok0gg1s" updated="20230625104207"}
git push -u origin 分支名
{: id="20230625104207-ccxw42z" updated="20230625104207"}
ERROR: Permission to XXX.git denied to user
ERROR: Permission to hbxn740150254/BestoneGitHub.git denied to Chenzuohehe. fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository exists.
https://www.jianshu.com/p/12badb7e6c10
Github README 无法加载图片
域名污染,需要在绕过 DNS 解析图片链接的域名,在/etc/hosts 文件中直接配置 ip
{: id="20230625104207-qei48io" updated="20230625104207"}
xxx.xxx.xxx.xxx raw.githubusercontent.com
{: id="20230625104207-9xpejtv" updated="20230625104207"}
xxx.xxx.xxx.xxx githubusercontent.com
{: id="20230625104207-0c3boxo" updated="20230625104207"}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于