介绍了git的常用操作。另外,记录了使用git时遇到的问题以及解决方案。

introduction

repository

zones

workspace

stage/index

branch

01 远程同步
git pull # 从远程仓库拉取最新的代码到本地
03 分支切换
git checkout test # 切换到“test”分支

在本地切换分支时,如果当前分支还没有执行addcommit,会遇到警告。切换到目标分支后,本地的文件会自动更改为目标分支的文件。

05 分支合并
git merge test # 把test分支的内容合并到当前分支中。
git merge --abort # 撤销最后一次合并

commit

merge commit

reference 这种方法并没有真正删除历史记录和commit,只是用 git log --oneline 等查看日志的命令时,使日志看起来变少

delete commit

reference

git log --oneline # 获取commit记录
git rebase -i <first_commit> # 根据上一个命令得到的结果

会进入一个如下所示的文件

  1 pick ba07c7d add bootstrap theme and format import
  2 pick 7d905b8 add newline at file last line
  3 pick 037313c fn up_first_char rename to caps
  4 pick 34e647e add fn of && use for index.jsp
  5 pick 0175f03 rename common include
  6 pick 7f3f665 update group name && update config

将想合并的提交的pick改成s,如

  1 pick ba07c7d add bootstrap theme and format import
  2 pick 7d905b8 add newline at file last line
  3 pick 037313c fn up_first_char rename to caps
  4 s 34e647e add fn of && use for index.jsp
  5 pick 0175f03 rename common include
  6 pick 7f3f665 update group name && update config

这样第四个提交就会合并进入第三个提交。 等合并完提交之后再运行

git push -f # 强制提交,会覆盖冲突的部分。不建议使用。

git gc --prune=now # 启动垃圾收集过程,Git会进行多个优化操作,包括压缩文件(打包未打包的对象)、删除无用的对象文件和重用打包的对象等
                   # 立即删除这些不再被任何引用的对象

edit history commit

reference

reset

git reset --soft HEAD^ # 撤销最近一次commit,不撤销 git add,保留对应的修改
git reset --soft HEAD~3 # 撤销最近三次commit,不撤销 git add,保留对应的修改
git reset --mixed HEAD~3 # 撤销最近三次commit,撤销 git add,保留对应的修改
git reset --hard HEAD~2 # 撤销最近两次commit,撤销 git add,删除两次提交对应的修改
git reset --hard origin/main # 将本地仓库指向分支“main”的最新commit提交,放弃所有更改

git checkout -f mainwindow.cpp # 放弃所有未提交的修改

If you run git reset --soft HEAD^ by mistake, you can run git reflog to look for the commit message of the reset commit (it will have a record like HEAD@{1} showing commit before the reset) and use that message to recommit. Or you can run git reset --soft HEAD@{1} to fully undo the git reset(move HEAD back to the original commit).

delete file and folder from git

删除指定文件的git记录

# 下载git-filter-repo工具
git clone https://github.com/newren/git-filter-repo.git
# 安装
cd git-filter-repo/
sudo cp git-filter-repo /usr/local/bin
# 下载对应的库(如果不重新下载,可能会出错,参照后面的说明)
git clone url
# 删除记录。以下示例为删除了一个PDF文件。这个操作会删除远程仓库链接和分支的配置信息。
git filter-repo --invert-paths --path "2019 Fast 3D Line Segment Detection From Unorganized Point Cloud.pdf"
# 删除记录。以下示例为删除了一个文件夹。这个操作会删除远程仓库链接和分支的配置信息。
git filter-repo --invert-paths --path docs
# 强制上传到远程仓库,url为远程仓库的链接,branch为指定的分支。必须添加"--force"选项,否则会失败
git push --force url branch

如果没有重新下载,直接删除记录可能会遇到如下错误

Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.

这是 git filter-repo 要求您在一个新克隆的仓库上运行以确保安全。这个安全措施是为了防止无意中重写并破坏正在使用的仓库的历史。由于 git filter-repo 可能会永久修改仓库的提交历史,使用一个新克隆的仓库可以避免错误地覆盖重要的工作。

如果遇到以下错误

fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using

说明没有指定远程仓库的地址和分支。

删除所有历史记录中当前提交不存在的文件

# 删除所有历史记录中当前提交不存在的文件
git filter-repo --invert-paths --path-glob '!*'
# 压缩并清理仓库
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# 推送到远程仓库
git push --force

perform something when commit

  1. create or edit file .pre-commit in folder .git/hooks/pre-commit.
  2. add operation you want to perform before commit with grammer shell. Here is an example to add date and time to file. ```bash #!/bin/bash

Set the folder and suffix filter

TARGET_FOLDER=”_posts” FILE_SUFFIX=”.md”

Get the current date and time with time zone

DATE_TIME=$(date “+%Y-%m-%d %H:%M:%S %z”)

Find files with the specific suffix in the target folder

for file in $(git diff –cached –name-only | grep “^$TARGET_FOLDER” | grep “$FILE_SUFFIX$”); do # Update the date line in the 4th row that starts with “date: “ sed -i “4s/^date: .*/date: $DATE_TIME/” “$file”

# Stage the modified file
git add "$file" done ``` 3. make commit as usual. the `git` will perform `pre-commit` and then perform git-commit as usual.

tag

List Available Tags

git tag

jump to the specific tag

git checkout v1.0.0

After checking out a tag, you will be in a “detached HEAD” state. This means that you’re not on a branch, but rather on the commit the tag points to. If you make changes and commit them in this state, those changes will not belong to any branch unless you explicitly create one.

configuration

一、 git 操作

1. commit处理

03

如果提交的内容比较多,需要进行补充说明的,可以执行命令

git commit --amend

会通过vim 打开一个文件,按下’o’,进行换行输入,距离第一行需要有一个空行,输入的内容可以是中文。

12 pre-commit

03. git信息查询

git branch -a # 确定当前的开发分支
git log # 查看commit提交记录
git log -- readme.md # 查看单个文件的提交记录
git log --shortstat # display all commits along with the number of lines changed (added and removed)
git log --pretty=format:"%h - %an: %s" --shortstat # output with only commit hashes and stats
git log --pretty=format:"" --shortstat #  Show Only Stats Without Commit Messages
git log --pretty=format:"%h - %an: %s" --shortstat | awk 'NF' # ensures only non-empty lines are displayed, producing cleaner output.

git diff # 查看具体的文件修改细节
git diff --shortstat # get a concise summary of the number of unstaged changed files, insertions and deletions. Untracked files are not included
git diff --numstat # get a machine-readable format
git diff --cached --shortstat # --cached: This option shows the differences between the staged changes and the HEAD

git config -l # 查看所有配置
git config --system --list # 查看系统配置
git config --global --list # 查看本地全局配置
format

--pretty=format

Placeholder Description
%H Full commit hash
%h Abbreviated commit hash
%T Full tree hash
%t Abbreviated tree hash
%P Full parent hashes
%p Abbreviated parent hashes
%an Author name
%ae Author email
%ad Author date (can be customized with –date)
%s Commit message
%d Refs (e.g., branch and tag names)

05 git特殊文件处理

.gitignore

一个文本文件,用于告诉 Git 哪些文件或目录是可以忽略的,不应该被包括在版本控制中。

*.tmp # 忽略所有以 .tmp 结尾的文件。
node_modules/ # 忽略整个 node_modules 目录,递归生效,忽略整个仓库中的该命名文件夹
/folderName/ # 仅忽略根目录中的文件
!lib.tmp # 不忽略 lib.tmp 文件,! 前缀用于否定一个模式。
.gitattributes

为特定文件和目录设置特定的Git属性,例如如何处理换行符差异。文件每一行都定义了一条规则,其基本格式为[pattern] [attribute]=[value]

* text=auto # 让Git自动判断文件是否为文本文件,对于文本文件,Git将会在内部处理它们以保证换行符的一致性。
* -text # 停止自动将文件视为文本文件进行换行符样式的自动识别和转换
*.sh text eol=lf # 保证所有 .sh 脚本文件在检出时使用 LF
*.jpg binary # 指定 .jpg 文件为二进制,避免进行文本比较或合并

07 submodule

在仓库中需要使用另一个仓库的内容,可以使用submodule将另一个仓库作为子仓库引入到当前仓库。

全部引入

使用以下命令引入子仓库

cd main-repo
git clone sub-repo
git add sub-repo
git commit -m "add sub-repo"

使用以下命令更新子仓库

cd main-repo
cd sub-repo
git checkout your_branch # change to some branch
git pull # get new from remote repo
cd ..
git add sub-repo
git commit -m "update sub-repo"
引入部分文件或文件夹

使用以下命令引入子仓库

git clone --filter=blob:none --no-checkout sub-repo # just create git, no file will be downloaded
cd sub-repo
git sparse-checkout init --cone # init sparse-checkout
git sparse-checkout set path-to-file-or-folder # set file and folder you need
git checkout # download or update

使用以下命令更新子仓库

cd sub-repo
git fetch # download from remote repo
git reset --hard origin/main # sync local repo with remote repo
clone and update a repository that contains submodules

if haven’t cloned main repo

git clone --recurse-submodules <repository_url>

if have clone main repo

git submodule update --init --recursive

update submodule

git submodule update --remote --merge

08 gitignore

Follow steps below to specify files or folders to be ignored across all your repositories by creating or editing a global gitignore file.

step
  1. Create a Global Ignore File: Choose or create a file to act as your global ignore file. For example:
    touch ~/.gitignore_global
    
  2. Set the Global Ignore File in Git Config: Configure Git to use this file as the global ignore file:
    git config --global core.excludesfile ~/.gitignore_global
    
  3. Add the patterns for files or folders you want to ignore. Pattern is same with .gitignore
  4. Verify the Configuration: Check that Git recognizes the global ignore file:
    git config --get core.excludesfile
    
Important Notes
  1. Global ignores are applied across all your repositories but only on your machine.
  2. They do not affect other users or collaborators. These rules won’t work for files or folders already tracked by Git. If you need to stop tracking a file or folder, you must first remove it from the repository: git rm --cached <file_or_folder>

This approach is helpful for ignoring files related to your development environment or specific tools without modifying each repository’s .gitignore.


五、Q&A

01. git

I got this when I execute git push

fatal: unable to access 'https://github.com/blue-stone-j/cloud_process.git/': GnuTLS recv error (-110): The TLS connection was non-properly terminated.

It’s caused by proxy. refer here.

03.

I got this when I executed git status

fatal: detected dubious ownership in repository at '/mnt/usb-Seagate_Expansion_NA8NNNVF-0:0-part1/00mygit/loam/cloud_process'

reason: User is jp when I execute “git status”, but owner of this folder is root. solution: change owner by chown new-owner filename; or execute with sudo like sudo git status

05.

出现以下错误提示

cannot rebase: Your index contains uncommitted changes.
fatal: invalid upstream 'master'

尝试以下命令

git stash

This a reference.

07

I met this when I executed git add ..

warning: adding embedded git repository:

This happened because there’s a repo in my this repo. I ignored it and continue commit-push. But I found there wasn’t files in warning folder in GitHub. The explaination is here. In a word, 在本地初始化的仓库(使用 git init的文件夹) 中的某一个文件夹,也含有 .git 文件 。.I deleted all .git and it works.

09

ssh: connect to host 192.168.10.180 port 22: Connection refused fatal: Could not read from remote repository.

Thie remote repoditory supports only http. But I cloned it by “ssh”. Then I met it when I pushed it to remote repository.

11

运行git clone时遇到错误GnuTLS recv error (-110): The TLS connection was non-properly terminated.。这可能是因为下载的库是private。

13

git log dc96b837cf6, then I got error: fatal: ambiguous argument 'dc96b837cf6': unknown revision or path not in the working tree.. The error message indicates that the commit ID (dc96b837cf6) does not exist in the current repository, or it is not reachable from your current branch or working directory.

六、其它

1.开源协议

pic6

.git

All files in folder .git won’t be pushed to remote.