git-howto
- improve git pull speed
- improve terminal speed (lagged/delayed by git)
- git auth
- git merge
- git rebase
git apply/am
(git patch)git submodule
git commit
git reflog
- git diff
- show config info (global)
- github cli
git lfs
: About Erasing Large File Commit in the Git History- git cancel
reset --hard
- git pull --ff-only
- git exclude
.gitignore
file
improve git pull speed
resolution 1: config proxy (vpn required)
how to config:
HTTP_PROXY=localhost:7890
git config --global http.proxy HTTP_PROXY
git config --global https.proxy HTTP_PROXY
confirm config:
config result:
resolution 2: change url
github.com
--> github.com.cnpmjs.org
ref:
improve terminal speed (lagged/delayed by git)
git config --add oh-my-zsh.hide-status 1
git config --add oh-my-zsh.hide-dirty 1
git auth
gitlab 每次都要输入密码的解决方案
分两步解决,首先要把自己的 ssh 公钥加入到 gitlab 用户配置里。
其次,还要设置远程仓库为 git 链接,而非 http(私库)。
# step 1. generate ssh-key if not exist
ssh-keygen -t rsa -C "shawninjuly@gmail.com" -b 4096
# step 2. show the ssh-public-key if generated
cat ~/.ssh/id_rsa.pub
# step 3. copy it into gitlab user settings
# step 4. test connection
ssh -T git@192.168.0.237
# Welcome to GitLab, @markshawn!
# step 5. set repo url to be git format (init first)
git remote set-url origin git@192.168.0.237:markshawn/hmdservice.git
ref:
official password and authentication
ref:
FIXED: GitHub does not provide shell access
Just change the remote url from https
to git
:
raw: https://github.com/arpara-vr/arpara-timewarp.git
then: git@github.com:arpara-vr/arpara-timewarp.git
git remote set-url origin git@github.com:arpara-vr/arpara-timewarp.git
git push
ref:
git merge
resolution 1
background:
本来想在surfaceflinger
下操作全部 git 的,结果发现最后还是要动到外面的renderengine
。
之前是在native
下进行 git 管理的,这本来很 ok,后来因为景喆/西瓜的 hmdservice
放了进来,导致 git 一下就脏了,所以才想到与它的 service 隔离,缩小到 surfaceflinger 范围。
现在发现不可行,不过正好 hmdservice
已经让博文去搞了,所以我又可以了,那就还是在 native
下管理,可是现在 surfaceflinger
下已经有几个 commit 了,所以就涉及到迁移/合并问题。
resolution:
这里是否可以把 Bproject 设成/path/to/B 呢?这样是不是就不用生成新的文件夹了?
update:不是,跳过git read-tree
步骤就可以。
git remote add -f Bproject /path/to/B
git merge -s ours --no-commit --allow-unrelated-histories Bproject/master
# git read-tree --prefix=dir-B/ -u Bproject/master
git commit -m "Merge B project as our subdirectory"
# git pull -s subtree Bproject master
ref:
FIXME: resolution 2 (maybe can be merged with 1)
!!!warning 这种方法只适合合并 git 追踪的文件,这将很容易导致一些问题,因为那些不被追踪的文件没有合并进来,比如我的 VERSION.txt
If you want to merge project-a into project-b:
cd path/to/project-b
git remote add project-a /path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a
ref:
git rebase
通过 glola
可以发现,我们当前的版本,和 upstream 从 2a043ea 开始产生了分歧:
所以此时推 upstream 是会被拒绝的,例如:
而 git 默认的提示是 使用 git pull
,也就是先把最新的 upstream 拉下来,这其实就是一个 merge
的操作。
当我们这样做之后,等于是我们消化了 upstream,等我们改完冲突之后再 push 时,分支树就类似这样走:
但其实,这并不是最优雅的动作,因为为了解决你和 upstream 之间的这个 merge
问题,你似乎往回走了一步 (俗称非线性)。
有一种办法可以让整个流程看起来更顺畅,那就是想方设法变成从 upstream 通向你:
这就是 rebase
。
rebase
是一个捏造词,也就是字面意义,重新 base 的意思,base 就是选择一个基底,按照我们的要求,我们只要选择 upstream 作为基底即可。
要使用 rebase
我们得先回到分叉口(或之前):
git checkout 2a043ea # 查询 git log 得知的分叉口
然后 rebase
到 upstream:
git rebase upstream/main
git apply/am
(git patch)
git patch workflow
ref:
Step 1. 下载 patch 文件
Step 2. 解压
此时假设文件路径在 FILE.diff
,工程路径为frameworks/native/
Step 3. (可选)显示有哪些文件会被改动
git apply --stat $FILE.diff
Step 4. 检测 patch 是否可行
git apply --check $FILE.diff
如果没有输出,说明可行。
否则,说明此 patch 不可行,可能缺少之前的 patch 步骤
Step 5.1 git am --signoff <
git am --signoff < $FILE.diff
该命令也许会有一些 warning,但都是编码质量方面的,只要 check 那步没问题这一步就没问题。
打完之后,不放心可以打开某几个文件检查一下,看看代码是否修改成功。
step 5.2 git apply -3
(solving error: fatal: empty ident name (for \<\>) not allowed
)
git apply --reject PATCH_FILE
git apply -3 PATCH_FILE
ref
Getting 'fatal: empty ident name not allowed' when doing 'Git commit --amend' - Stack Overflow
github - git : empty ident name (for \<>) not allowed - Stack Overflow
"git apply" gives error "does not match index" when a previous apply skips hunks - Stack Overflow
patch - What to do if git-am fails with "does not match index"? - Stack Overflow
merge git patch files
ref:
Step 1. download combinediff
release url: Index of /tim/data/patchutils/stable
target latest download url(2022-01-25): patchutils-0.4.2.tar.xz
Step 2. build combinediff
extract the
xxx.tar.xz
./configure && make && make install
Step 3. use combinediff
# combine
combinediff FILE1.diff FILE2.diff > merged.diff
# interpolate FILE1 - FILE2
combinediff --interpolate FILE1.diff FILE2.diff > interpolate.diff
Usage of combinediff --interpolate
# drop all the only diffs in patch2
perl -i.bak -0pe "s|^only in patch2.*||smg" interpolate.diff
# drop a specific big diff
# if there is "+++", you should use "\"
perl -i.bak2 -0pe "s|reverted:
--- b/services/surfaceflinger/HmdType6DistortionMesh.cpp.*?(?=reverted)||smg" interpolate.diff
# check the size difference of `xx | xx.bak | xx.bak2`
l | grep interpolate
# show the html
# ref: https://github.com/rtfpessoa/diff2html-cli#setup
diff2html -i file --style side -- interpolate.diff
git submodule
ref:
config submodule
(.pyenv) ➜ mark_keeps_learning git:(master) ✗ cat .gitmodules [23-01-22 | 5:39:31]
[submodule "whats-the-best-to-learn"]
path="whats-the-best-to-learn"
url="https://github.com/whats-the-best/whats-the-best-to-learn"
init and push submodule
git submodule init
git push
add submodule
git submodule add URL PATH
git commit
git remove a specific from specific commits
conclusion
FILE="XXX"
git reset --soft HEAD^
git reset HEAD $FILE
git rm -- cached $FILE
git commit --amend
detail
# step 1. stage all the committed files
git reset --soft HEAD^
# step 2. remove file from staging area
git reset HEAD <FILENAME>
# step 3. rm file from cached
git rm -- cached <FILENAME>
# step 4. re-commit
git commit --amend
ref:
core ref: How to Remove a File from Commit in Git
❌ bad ref: How To Remove Files From Git Commit – devconnected
git remove specific file from history
# solution 1. using `git filter-branch`
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <path to the file or directory>' --prune-empty --tag-name-filter cat -- --all
# solution 2. using `git filter-repo`
pip3 install git-filter-repo
git filter-repo --path <path to the file or directory> --invert-paths
ref:
git merge commits (reset)
ref:
Step 1. reset
# this would reset to before the SHA_ID (i.e. keep the SHA_ID, but remove all the commits before)
git reset --soft SHA_ID && git commit
Step 2. push
# since the commits are changed, the normal `push` won't help, you need to use `--force`
git push -f
git commit amend
!!!warning Use the git commit --amend
only when files are not changed, otherwise use a new commit and use the git reset --soft
if need to merge the history commits.
git commit --amend
git push -f
ref:
generate diff file from commit
# check sha
git log --oneline
# generate diff
git diff <commit-sha> -p
# generate diff to file
git diff COMMIT_SHA -p > DIFF_FILE
ref:
git reflog
customized git reflog
git reflog --format="%C(auto)%h %<|(17)%gd %C(blue)%ci %C(reset)%an %C(green)%gs"
The core concept is at Git - pretty-formats Documentation, and I explored the following formats relatively satisfying.
--oneline
for short and easy to remembergit reflog --oneline
--date=iso
for short and datetime displaygit reflog --date=iso
--format="%h %gd %ci %gs"
for full infogit reflog --format="%h %gd %ci %gs"
for alignment of HEAD, since it may be two-digit
git reflog --format="%h %<|(17)%gd %ci %gs"
[RECOMMEND] for alignment and color print
git reflog --format="%C(auto)%h %gd %C(blue)%ci %C(reset)%an %C(green)%gs"
with align
git reflog --format="%C(auto)%h %<|(17)%gd %C(blue)%ci %C(reset)%an %C(green)%gs"
I quite love this color scheme!
clean reflog (unreachable)
git reflog expire --expire=90.days.ago --expire-unreachable=now --all
before clean:
There are a lot of reflog entries, and a lot of them are unreachable (just a record).
after clean:
It becomes clean.
ref:
delete one specific reflog entry
git reflog delete SHA_ID
ref:
git diff
only show file names
git diff XXX --name-only
set tab width to be 4
git config --global core.pager 'less -x1,5'
ref:
show config info (global)
git config --list
It's same to run as:
cat ~/.gitconfig
github cli
documentation:
usage sample:
git lfs
: About Erasing Large File Commit in the Git History
ref:
Conclusion
clear commands
!!!warning 1. 注意grep
不支持强化正则,比如 positive/negative lookahead/lookbackward,以及$这些 2. 如果一定要使用这些,推荐尝试perl
或者awk
EXCLUDE_RE="life/王者荣耀"
# 有时需要加 `-f` 参数
# 删除全部
git filter-branch --prune-empty --index-filter "git rm --cached -rf --ignore-unmatch ${EXCLUDE_RE}" --tag-name-filter cat -- --all
# 删除从某个commit到ref(比如HEAD)
git filter-branch -f --prune-empty --index-filter "git rm --cached -rf --ignore-unmatch ${EXCLUDE_RE}" --tag-name-filter cat $COMMIT_ID...HEAD
执行成功后将会有修改记录输出,如下:
check if file exists in history
git log --graph --decorate --pretty=oneline --abbrev-commit --all --name-status | grep -E ${EXCLUDE_RE}
check log history
git lola
push if ok
git push
PR: update to use git filter-repo
Details
这个问题的原因找到了,就在于我曾经 add 了大文件,然后又 delete 了,虽然文件已经不在了,最新的 commit 里也没有这个文件了,但是 history 里有,于是 git 不允许我 push commit,要么我采取 lfs(large file storage)的方法,要么想办法把这个记录从 history 里删掉:
git log --graph --decorate --pretty=oneline --abbrev-commit --all --name-status | grep -E "Electron Framework$|^\*"
最后用这个命令,把 git history 中所有与那个大文件相关的(即 node_modules 文件夹)都删除就可以了:
git filter-branch --prune-empty -d ~/temp \
--index-filter "git rm --cached -rf --ignore-unmatch mark_learns_coding/JS/MarkLearningWebpack/demo7/node_modules" \
--tag-name-filter cat -- --all
Acknowledgement: 非常感谢 stackoverflow 大佬专业又详细的回答,没有大佬的解答,我可能又要耗费一个通宵才能解决这个相对比较罕见的问题了:https://stackoverflow.com/a/2158271/9422455
另外,他使用的git lola
很有用,需要在~/.gitconfig
文件中加入以下:
# git lola | Conrad Parker, http://blog.kfish.org/2010/04/git-lola.html
[alias]
lol = log --graph --decorate --pretty=oneline --abbrev-commit
lola = log --graph --decorate --pretty=oneline --abbrev-commit --all
[color]
branch = auto
diff = auto
interactive = auto
status = auto%
这样就可以使用酷酷的git lola
命令了(可以显示历史变动情况),如果加上git lola --name-status
之后还可以看到每次 git 会对哪些文件产生怎样的影响,非常好用!
ref:
- Git - git-log Documentation
- git lola | Conrad Parker
- version control - How to remove/delete a large file from commit history in the Git repository? - Stack Overflow
- About large files on GitHub - GitHub Docs
git cancel reset --hard
git reflog # to show the hashId list, select one
git reset --hard HASH-ID
ref:
git pull --ff-only
With git pull --ff-only, Git will update your branch only if it can be “fast-forwarded” without creating new commits. If this can’t be done, git pull --ff-only simply aborts with an error message. You can configure your Git client to always use --ff-only by default, so you get this behavior even if you forget the command-line flag:
git config --global pull.ff only ref: https://stackoverflow.com/a/62653400/9422455
git exclude .gitignore
file
echo .gitignore >> .git/info/exclude
ref: