Git 开发日常

8 篇文章 0 订阅

Traditional Ways

[分支名]$ git checkout -b dev   #开发的时候创建一条自己的分支
############################
########## 开发 #############
############################
[dev]   $ git rebase -i master  #合并提交记录
# 切换到 master 分支拉取最新代码
[dev]   $ git checkout master
[master]$ git pull
[master]$ git checkout dev
# 将最新代码合并到 dev 分支
[dev]   $ git rebase master     #有冲突解决冲突,继续:git rebase --continue
# 推送远程
[dev]$ git push origin dev:dev

[gitlab-web] 在网页端提交 Merge Request
或开发负责人(有 master 权限的人)自己合并
[dev]   $ git checkout master
[master]$ git merge dev

Tips: 重心放在本地。除了 git push, 其他常用命令不会对远程仓库造成破坏性影响

常用命令

一、版本回退

  • 回退 git add
# git restore 在 2.23.0 中引入(与 git switch 一起)专为 unstage
git restore --staged <file>
# 旧版
git reset <file>
# To unstage a specific file
git reset HEAD <file>
# To unstage all files from the current change set:
git reset
  • 回退 git commit
# 1. 实验:本地回退版本,硬回退(适合自己一个人玩,回退私人仓库的)
$ git reset --hard origin/master	#本地分支和远程分支保持一致
$ git reset --hard Oldid			#回退旧版本
$ git push -f						#优点:版本线会比较干净 (但如果别人已经拉到本地, 别人再次拉取更新将会造成冲突)
# git 2.30 更新了2个参数
$ git push --force-with-lease --force-if-includes
## 第一个很好理解, 如果最新的更新没有他人就推送成功
## 第二个其实应该叫 --force-if-local-head-matches-remote-head 

# 2. 真正的远程回退:revert,意思是撤销某次提交。它会产生一个新的提交,虽然代码回退了,但是版本依然是向前的,所以,当你用revert回退之后,所有人pull之后,他们的代码也自动的回退了。
$ git revert HEAD~1 	#从0开始, 这是回退上上次
HEAD^1==HEAD~1  HEAD^^==HEAD~2!=HEAD^2

# 3.错的太远了直接将代码全部删掉,用正确代码替代
  • 使用 git checkout <file> 回退
    • 前面加 -- 是文件, 后面加 -- 是分支
    • git checkout 不能重置已经 git add 过的文件

git 中,双破折号 -- 用于区分命令选项和参数。它的作用是明确告诉 git,其后的内容应该被视为参数,而不是选项

git checkout file_path
# or 如果分支名和文件夹名相同, 则需要在前面添加 -- 来指定是文件
git checkout -- file_path

# ps: 在后面添加 -- 是指定分支
git checkout develop --

二、分支管理

# 0 如果有分支和文件夹名称重复, 可在后面加 "--" 来特定为分支
$ git checkout develop --
# 1. 新分支同步到远程分支
$ git push [-u] origin local-branch:remote-branch
or
## Failure to perform the –set-upstream step will causes pushes of the new branch to the remote repo to fail with the following error:
## fatal: The current branch has no upstream branch
$ git push –set-upstream origin new-branch
$ git push -u origin new-branch

# 2. 本地拉取远程分支(默认只有主分支会拉) -t, --track[=(direct|inherit)] When creating a new branch, set up "upstream" configuration
$ git checkout -t origin/branchName

# 3. 删除远程分支
$ git push origin :dev					#推送一个空分支(:前面为空)到远程分支,其实就相当于删除远程分支
or 
$ git push origin --delete <remote-branchname>	#git push origin -d 另外,-dr(-d加-r)只删除git branch -r列表中的{追踪分支},并不删除远程分支。

# 4. 新建空白分支
$ git checkout --orphan null_branch		# 必须初始化提交,再push:git commit -am "Init commit."
$ git rm -r --cached .
$ git commit -am "init commit"			# 必须提交初始化commit,再push到远程仓库
如何转移 Git 仓库

三、跟踪(远程与本地相关联)

# 1. 建立连接(曾经是set-upstream后面改为set-uptream-to)
$ git branch --set-upstream-to=origin/dev   
$ git branch -u origin/dev

# 2. 取消对master的跟踪
$ git branch --unset-upstream master

# 3. 查看当前分支的upstream(跟踪情况)
$ git branch -vv

四、打tag标签

tag 标签是指向commit的死指针,分支是指向commit的活指针。
tag 在不同分支能看到,是因为该提交记录在不同分支都有,tag与commit绑定。(stash也能在不同分支看到,但这是因为stash与暂存区有关,不同分支都共用的一个暂存区)

$ git tag v0.1  # "v0.1"就是tag名
# 当没有指定哪一条提交记录是默认为HEAD,也就是当前最近的一条提交记录。
$ git tag v0.1 f52c633  # 指定提交记录打tag
$ git tag  # 查看所有tag标签
$ git tag -a v0.1 -m "描述信息"
$ git show v0.1 # 查看标签的说明文字
$ git tag -d v0.1 # 删除
# tag 只存在本地,不会自动推送到远程。
$ git push origin v1.0 # 推送一条
$ git push origin --tags # 推送所有tag
# 删除远程tag
$ git tag -d v0.1 && git push origin :refs/tags/v0.1
# 查看效果
$ git ls-remote --tags origin

五、Git Rebase

把dev分支接到master的后面

$ git rebase <new base> <branch name>

[master分支]$ git checkout dev
[  dev 分支]$ git rebase master [dev]    # master 合到 dev, 以 master 为基准

master在前, dev在后   < 新基准 >   < 分支名 >

六、git rebase -i

  • 语法: git rebase -i [startpoint] [endpoint]

其中 -i 的意思是 --interactive ( 交互式的进行, 即vi式 ), 不写 endpoint 默认为 HEAD , 并且该区间为 (start,end] 前开后闭区间.

startpoint endpoint 不允许设为初次提交 (最好不要在 初次提交 中提交代码, 本应该提交的是 README.md 之类)

p pick:保留该 commit(缩写 p)
r reword:保留该 commit,但我需要修改该commit的注释(缩写 r)
e edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写 e)
s squash:将该commit和前一个commit合并(squash 压碎, 缩写 s)
f fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写 f)
x exec:执行shell命令(缩写 x)
d drop:我要丢弃该commit(缩写 d)

p 原样、r 改msg、e 修改提交、s 压缩并编辑、f 直接与上一个压缩、d 丢弃

  • 示例
$ git rebase -i 36224db (ps:不包含36224db这条记录, 如需要包含则写36224db^)  
或
$ git rebase -i HEAD~3 
$ git rebase -i master	#表示基于master合并多次提交,并改变自己的历史提交记录,以保持远程仓库的历史为一条直线,不会有merge一行
会进入两个选项:pick、s代表跳过
还会有commit信息重新编辑
git rebase -i HEAD~3
# pick 修改为 edit 或 e
# 修改之前提交的信息
git add
git commit --amend
git rebase --continue
# (END)
# 还有其他命令 git rebase --abort 中止
# continue 之后导致空补丁显示已经应用, 根据提示信息进行跳过 git rebase --skip
git show 50f6a1ab # 查看 50f6a1ab 这个 commit记录
  • 拆分提交 (i.e., 不使用 --amend)
git reset HEAD^
git add main/*
git ci -m 'fix:step 1 XXX'
git add test/*
git ci -m 'fix:step 2 XXX'
git rebase --continue
  • 更改提交顺序 (其余步骤省略)
pick A change A
pick B change B
pick C change C
# 修改弹出的交互文件
pick B change B
pick A change A
pick C change C

七、Git Rebase <新内容分支> --onto <旧分支>

  • 复制某个区间的提交记录到另一个分支
~第一步: 
$ git rebase 90bc0045b^ 5de0da9f2 --onto master 
onto意思为: git rebase <after this commit> <to this commit> --onto <new base> 
~此时master的HEAD处于游离状态(detached HEAD), git只是将区间部分的提交内容复制一份粘贴到了master所指向的提交后面, 我们需要将master所指向的HEAD设置为当前指向的提交id.
$ git checkout master
$ git reset --hard  0c72e64 (左边为, checkout master显示的id)
  • 如果是单独挑选几个游离的提交进行复制, 可以使用 git cherry-pick
$ git checkout dev
$ git cherry-pick 60cd8ab 1988bca d83549a
意思是: 复制上面三个提交记录到dev分支(这个三个提交是其他分支的)

八、密钥生成

  • 生成密钥,用于连接远程仓库无需使用密码,原理见我的另一篇博客
$ ssh-keygen -t rsa -C "your_email@example.com"
-- -t 代表 type 指定要创建的密钥类型。可以使用:"rsa1"(SSH-1) "rsa"(SSH-2) "dsa"(SSH-2)
-- -C comment,提供一个新注释;
-- -c 要求修改私钥和公钥文件中的注释;只支持 RSA1 密钥;程序将提示输入私钥文件名、密语(如果存在)、新注释。

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
-- -b bits 指定密钥长度。对于RSA密钥,最小要求768位,默认是2048位。DSA密钥必须恰好是1024位(FIPS 186-2 标准的要求)
  • 上面的密钥对生成在~/.ssh/目录下,我们可以生成在当前文件夹下另作它用。
$ ssh-keygen -t rsa -C "注释" -f "文件名"

九、".ssh文件夹"迁移

  • 以下是迁移文件夹到Linux系统电脑上, 达到复制密钥的目的. (当然, 你可以重新生成密钥并添加GitHub)
$ chmod 755 ~/.ssh/  
$ chmod 600 ~/.ssh/id_rsa ~/.ssh/id_rsa*  
$ chmod 644 ~/.ssh/known_hosts 
#在~/.ssh/目录下
$ eval "$(ssh-agent -s)"    # eval (start the ssh-agent in the background) ssh-agent -s (Agent pid 59566 添加生成的 SSH key 到 ssh-agent)
--ssh-agent是一种控制用来保存公钥身份验证所使用的私钥的程序
--其实ssh-agent就是一个密钥管理器,运行ssh-agent以后,使用ssh-add将私钥交给ssh-agent保管,其他程序需要身份验证的时候可以将验证申请交给ssh-agent来完成整个认证过程。

$ ssh-add    #默认不写是加id_rsa
$ ssh-add id_rsa_github

$ ssh -T git@github.com  #测试连接
##

十、暂存与版本回退

--闪存
$ git stash
$ git stash list		   #看有哪些闪存
$ git stash show stash@{0} #看该闪存有哪些更改
--闪回
$ git stash pop
$ git status
$ git stash pop --index
--如果原来的文件修改已经添加到暂存区的,但用git stash pop 恢复进度后,修改却还在工作区,暂存区的修改被撤销了。这里运行git stash pop命令时带上一个 --index 的选项来告诉git重新应用被暂存的变更。

--撤销未保存的修改的
$ git checkout -- filename

--撤销add的
$ git reset HEAD a.txt
$ git log --oneline

--撤销本地commit
$ git reset --soft HEAD~1
--选项–soft 的作用就是把最新那次提交的所有改动撤回到暂存区。

--不再跟踪某个文件
$ git rm --cached a.txt  # -r 删除文件夹 目录可为.
$ git restore --staged a.txt # 两句效果一样,任选一句喜欢的

十一、assume-unchanged 忽略 yaml 配置文件的修改

  • 通常我们修改部分配置文件,只为了让项目在本地运行起来
  • 我们不想提交修改, 然后又不想让他们占着位置changelist的位置
# 忽略
$ git update-index --assume-unchanged src/main/resources/test.txt
# 取消忽略
$ git update-index --no-assume-unchanged src/main/resources/test.txt
# 查找忽略的文件(找到众多目录中, 以h开头标记的目录)
$ git ls-files -v |grep '^h'

十二、全局忽略 .gitignore

  • git 的全局配置文件在当前用户目录的 .gitconfig 文件下
  • 将自定义的全局 .gitignore 文件的绝对地址到配置 config 文件里
  • 推荐在当前用户目录下新建 .gitignore 文件,写入
target/
out/
dist/
*.iml
.idea/
.svn/
.vscode/
.DS_Store
.AppleDouble
  • 然后在命令行输入 git config 命令 core.excludesfile
## win 下使用 cmd 方式
$ git config --global core.excludesfile %USERPROFILE%\.gitignore
## linux / macOS
$ git config --global core.excludesfile ~/.gitignore
  • 全局忽略配置会立即生效

or vim ~/.gitconfig

[core]
    autocrlf = input
    excludesfile = ~/.gitignoreh
[init]
    defaultBranch = master
[alias]
    st = status
    ci = commit -m
    cl = clone
    co = checkout
    mwps = push -o merge_request.create -o merge_request.target=develop -o merge_request.remove_source_branch -o merge_request.merge_when_pipeline_succeeds
    ## skip-worktree assumes that the user intends to change the file.
    # ignore = !git update-index --skip-worktree
    # unignore = !git update-index --no-skip-worktree
    # --查找忽略的文件(找到众多目录中, 以h开头标记的目录)
    # lsi = !git ls-files -v |grep '^h'
    
    ## assume-unchanged assumes that the user will not change the file.
    ignore = !git update-index --assume-unchanged
    unignore = !git update-index --no-assume-unchanged
    lsi = !git ls-files -v |grep '^S'

十三、--assume-unchanged and --skip-worktree what’s the difference.

  1. git update-index --assume-unchanged
  2. git update-index --skip-worktree
  3. git ls-files -v

whereas skip-worktree assumes that the user intends to change the file, assume-unchanged assumes that the user will not change the file. The intention is different.

--assume-unchanged 简介 ('^h')

The –assume-unchanged option tells Git to temporarily assume that a tracked file has not been modified in the working tree. Therefore, changes made won’t be reflected in the staging area.
–asassume -unchanged 选项告诉 Git 暂时假定在工作树中未修改跟踪的文件。因此,所做的更改不会反映在暂存区域中.

the h tag indicates that assume-unchanged.txt is marked with the assumed-unchanged option.
在这里,h 标签表示用 assumed-unchanged option.

Although mainly used for that purpose, the assume-unchanged option was never meant to ignore changes to tracked files. It’s designed for cases where it’s expensive to check whether a group of files have been modified. What happens if we want to optimize resource usage on slow filesystems: git omits any checking against the target file and won’t compare its versions in the working directory and in the index.
虽然主要用于此目的,但假设不变选项从未打算忽略对跟踪文件的更改。它专为检查一组文件是否已被修改的成本很高的情况而设计。如果我们想优化慢速文件系统上的资源使用会发生什么:git 省略了对目标文件的任何检查,并且不会在工作目录和索引中比较其版本。

--skip-worktree 简介 ('^S')

The –skip-worktree option ignores uncommitted changes in a file that is already tracked. Regardless of any modification made in the working tree, git will always use the file content and attributes from the staging area. This is useful when we want to add local changes to a file without pushing them to the upstream:
–skip-worktree 选项忽略已跟踪的文件中未提交的更改。无论在工作树中进行任何修改,git 都将始终使用暂存区域中的文件内容和属性。当我们想要将本地更改添加到文件而不将它们推送到上游时,这很有用:

This option is automatically unset when the file changes in the index i.e., if the file’s been changed upstream and we pull it.
当索引中的文件更改时,此选项会自动取消设置,即文件已在上游更改并且被我们拉取时自动取消.

the S indicates that skip-worktree.txt is marked with the skip-worktree option
当使用命令3时, S 代表 skip-worktree option

区别

  1. 两者非常相似, 同时使用时, 优先使用 skip
    --skip-worktree takes precedence over --assume-unchanged bit when both are set.
  2. skip 签出分支没有问题
    There's no issue when checking out a branch when a file has the --skip-worktree option on. But, --assume-unchanged will raise an error
  3. assume 性能更好, 但 skip 更加方便.
  4. assume 一般用于大文件.

十四、Git message 编写

feat:更新了若干功能
fix:修复了一些已知问题
build:一些影响构建系统的更新
chore:家务活
ci:更改了ci配置
docs:对文档做出了一些修改
test:新增或修改测试文件
refactor:重构了代码
perf:性能提升
revert:撤销更改

feat(npm):描述

正文

脚注

@see https://github.com/pvdlg/conventional-changelog-metahub#commit-types

十五、Git + oh-my-zsh 缩写

-='cd -'
g=git
ga='git add'
gaa='git add --all'
gam='git am'
gama='git am --abort'
gamc='git am --continue'
gams='git am --skip'
gamscp='git am --show-current-patch'
gap='git apply'
gapa='git add --patch'
gapt='git apply --3way'
gau='git add --update'
gav='git add --verbose'
gb='git branch'
gbD='git branch -D'
gba='git branch -a'
gbd='git branch -d'
gbda='git branch --no-color --merged | command grep -vE "^([+*]|\s*($(git_main_branch)|$(git_develop_branch))\s*$)" | command xargs git branch -d 2>/dev/null'
gbl='git blame -b -w'
gbnm='git branch --no-merged'
gbr='git branch --remote'
gbs='git bisect'
gbsb='git bisect bad'
gbsg='git bisect good'
gbsr='git bisect reset'
gbss='git bisect start'
gc='git commit -v'
'gc!'='git commit -v --amend'
gca='git commit -v -a'
'gca!'='git commit -v -a --amend'
gcam='git commit -a -m'
'gcan!'='git commit -v -a --no-edit --amend'
'gcans!'='git commit -v -a -s --no-edit --amend'
gcas='git commit -a -s'
gcasm='git commit -a -s -m'
gcb='git checkout -b'
gcd='git checkout $(git_develop_branch)'
gcf='git config --list'
gcl='git clone --recurse-submodules'
gclean='git clean -id'
gcm='git checkout $(git_main_branch)'
gcmsg='git commit -m'
'gcn!'='git commit -v --no-edit --amend'
gco='git checkout'
gcor='git checkout --recurse-submodules'
gcount='git shortlog -sn'
gcp='git cherry-pick'
gcpa='git cherry-pick --abort'
gcpc='git cherry-pick --continue'
gcs='git commit -S'
gcsm='git commit -s -m'
gcss='git commit -S -s'
gcssm='git commit -S -s -m'
gd='git diff'
gdca='git diff --cached'
gdct='git describe --tags $(git rev-list --tags --max-count=1)'
gdcw='git diff --cached --word-diff'
gds='git diff --staged'
gdt='git diff-tree --no-commit-id --name-only -r'
gdup='git diff @{upstream}'
gdw='git diff --word-diff'
gf='git fetch'
gfa='git fetch --all --prune --jobs=10'
gfg='git ls-files | grep'
gfo='git fetch origin'
gg='git gui citool'
gga='git gui citool --amend'
ggpull='git pull origin "$(git_current_branch)"'
ggpur=ggu
ggpush='git push origin "$(git_current_branch)"'
ggsup='git branch --set-upstream-to=origin/$(git_current_branch)'
ghh='git help'
gignore='git update-index --assume-unchanged'
gignored='git ls-files -v | grep "^[[:lower:]]"'
git-svn-dcommit-push='git svn dcommit && git push github $(git_main_branch):svntrunk'
gk='\gitk --all --branches &!'
gke='\gitk --all $(git log -g --pretty=%h) &!'
gl='git pull'
glg='git log --stat'
glgg='git log --graph'
glgga='git log --graph --decorate --all'
glgm='git log --graph --max-count=10'
glgp='git log --stat -p'
glo='git log --oneline --decorate'
globurl='noglob urlglobber '
glod='git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset'\'
glods='git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset'\'' --date=short'
glog='git log --oneline --decorate --graph'
gloga='git log --oneline --decorate --graph --all'
glol='git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'\'
glola='git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'\'' --all'
glols='git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'\'' --stat'
glp=_git_log_prettily
gluc='git pull upstream $(git_current_branch)'
glum='git pull upstream $(git_main_branch)'
gm='git merge'
gma='git merge --abort'
gmom='git merge origin/$(git_main_branch)'
gmtl='git mergetool --no-prompt'
gmtlvim='git mergetool --no-prompt --tool=vimdiff'
gmum='git merge upstream/$(git_main_branch)'
gp='git push'
gpd='git push --dry-run'
gpf='git push --force-with-lease'
'gpf!'='git push --force'
gpoat='git push origin --all && git push origin --tags'
gpr='git pull --rebase'
gpristine='git reset --hard && git clean -dffx'
gpsup='git push --set-upstream origin $(git_current_branch)'
gpu='git push upstream'
gpv='git push -v'
gr='git remote'
gra='git remote add'
grb='git rebase'
grba='git rebase --abort'
grbc='git rebase --continue'
grbd='git rebase $(git_develop_branch)'
grbi='git rebase -i'
grbm='git rebase $(git_main_branch)'
grbo='git rebase --onto'
grbom='git rebase origin/$(git_main_branch)'
grbs='git rebase --skip'
grep='grep --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn,.idea,.tox}'
grev='git revert'
grh='git reset'
grhh='git reset --hard'
grm='git rm'
grmc='git rm --cached'
grmv='git remote rename'
groh='git reset origin/$(git_current_branch) --hard'
grrm='git remote remove'
grs='git restore'
grset='git remote set-url'
grss='git restore --source'
grst='git restore --staged'
grt='cd "$(git rev-parse --show-toplevel || echo .)"'
gru='git reset --'
grup='git remote update'
grv='git remote -v'
gsb='git status -sb'
gsd='git svn dcommit'
gsh='git show'
gsi='git submodule init'
gsps='git show --pretty=short --show-signature'
gsr='git svn rebase'
gss='git status -s'
gst='git status'
gsta='git stash push'
gstaa='git stash apply'
gstall='git stash --all'
gstc='git stash clear'
gstd='git stash drop'
gstl='git stash list'
gstp='git stash pop'
gsts='git stash show --text'
gstu='gsta --include-untracked'
gsu='git submodule update'
gsw='git switch'
gswc='git switch -c'
gswd='git switch $(git_develop_branch)'
gswm='git switch $(git_main_branch)'
gtl='gtl(){ git tag --sort=-v:refname -n -l "${1}*" }; noglob gtl'
gts='git tag -s'
gtv='git tag | sort -V'
gunignore='git update-index --no-assume-unchanged'
gunwip='git log -n 1 | grep -q -c "\--wip--" && git reset HEAD~1'
gup='git pull --rebase'
gupa='git pull --rebase --autostash'
gupav='git pull --rebase --autostash -v'
gupom='git pull --rebase origin $(git_main_branch)'
gupomi='git pull --rebase=interactive origin $(git_main_branch)'
gupv='git pull --rebase -v'
gwch='git whatchanged -p --abbrev-commit --pretty=medium'
gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign -m "--wip-- [skip ci]"'
gwt='git worktree'
gwta='git worktree add'
gwtls='git worktree list'
gwtmv='git worktree move'
gwtrm='git worktree remove'

hexo='npx hexo'
his=history
history=omz_history
l='ls -lah'
la='ls -lAh'
ll='ls -alF'
ls='ls -G'
lsa='ls -lah'
md='mkdir -p'

十六、统计代码行数

git log -1 --skip 5 --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

十七、同时更新目录下多个仓库代码

Reference: https://stackoverflow.com/questions/3497123/run-git-pull-over-all-subdirectories

  1. find
find . -type d -depth 1 -exec git --git-dir={}/.git --work-tree=$PWD/{} pull origin master \;

To clarify:

find . searches the current directory
-type d to find directories, not files
-depth 1 for a maximum depth of one sub-directory
-exec {} ; runs a custom command for every find
git --git-dir={}/.git --work-tree=$PWD/{} pull git pulls the individual directories
To play around with find, I recommend using echo after -exec to preview, e.g.:

find . -type d -depth 1 -exec echo git --git-dir={}/.git --work-tree=$PWD/{} status \;

Note: if the -depth 1 option is not available, try -mindepth 1 -maxdepth 1.

  1. xargs
ls |xargs -P10 -I{} git -C {} pull

-P parallel
-I “replace string” or “input placeholder”
-d ‘\t’(分割)
-p (打印询问)
-t (打印后直接执行)
-L 1(max-line)
-n 1(max-args)

  1. for

A bit more low-tech than leo’s solution:

for i in */.git; do ( echo $i; cd $i/..; git pull; ); done

This will update all Git repositories in your working directory. No need to explicitly list their names (“cms”, “admin”, “chart”). The “cd” command only affects a subshell (spawned using the parenthesis).

十八、离线如何通过本地文件备份 git 仓库

https://www.gibbard.me/using_git_offline/

Some companies use an isolated network or even the complete lack of a network as a security measure to protect from unauthorized access. Working on these systems can be a struggle but it is still possible, and perhaps even more important, to use a proper version control tool like Git.

By design Git works quite happily with no remote repository. You can branch, stage, and commit files just like normal.

mkdir testRepo
cd testRepo
git init
touch test.txt
git add --all
git commit -m "Initial Commit"

This works great if just a single machine is used for development, but this is often not the case.

Working with multiple machines — Using a USB memory stick/HDD
When security policy allows read/write access to a memory stick or portable hard drive a remote repository can be created on this device.

On one development machine mount the memory stick.

cd /path/to/memory/stick
mkdir repoName.git
cd repoName.git
git init --bare

Navigate to the repository that is to be shared, add the remote repository on the memory stick, and push the changes.

cd /path/to/local/repo/
git remote add origin /path/to/memory/stick/repoName.git
git push origin master

NB. The remote can be called anything. It doesn’t have to be called “origin”.

Unmount the memory stick and mount it on another development machine.

If the development machine does not have a copy of the repository on it already then git clone can be used.

git clone /path/to/memory/stick/repoName.git

If there is a copy of the repository already on the machine add the memory stick as a remote and fetch/pull the changes.

cd /path/to/local/repo/
git remote add origin /path/to/memory/stick/repoName.git
git pull origin

From now on use Git as normal but make sure that whenever a git pull, fetch, or push is performed the memory stick is mounted on the machine.

Ensure the memory stick is part of your backup routine.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值