git-xargs
is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command. You give git-xargs
:
and git-xargs
will:
Git-xargs leverages goroutines to perform the repo-updating work in parallel, so it is very fast.
For example, have you ever needed to add a particular file across many repos at once? Or to run a search and replace to change your company or product name across 150 repos with one command? What about upgrading Terraform modules to all use the latest syntax? How about adding a CI/CD configuration file, if it doesn't already exist, or modifying it in place if it does, but only on a subset of repositories you select?You can handle these use cases and many more with a single git-xargs
command.
As an example, let's use git-xargs
to create a new file in every repo:
git-xargs \
--branch-name test-branch \
--github-org <your-github-org> \
--commit-message "Create hello-world.txt" \
touch hello-world.txt
Here's what it looks like in action:
In this example, every repo in your org will have a new file named hello-world.txt written to it with the contents "Hello, World!". You'll then receive an easy-to-read printout of exactly what happened on STDOUT
:
*****************************************************************
GIT-XARGS RUN SUMMARY @ 2021-04-12 23:05:18.478435534 +0000 UTC
Runtime in seconds: 4
*****************************************************************
COMMAND SUPPLIED
[touch hello-world.txt]
REPOS SUPPLIED VIA --repos FILE FLAG
│────────────────────────│────────────────────────│
│ ORGANIZATION NAME (5) │ URL │
│────────────────────────│────────────────────────│
│ zack-test-org │ terraform-aws-asg │
│ zack-test-org │ terraform-aws-vpc │
│ zack-test-org │ terraform-aws-security │
│ zack-test-org │ terraform-aws-eks │
│ zack-test-org │ circleci-test-1 │
│────────────────────────│────────────────────────│
ALL REPOS THAT WERE TARGETED FOR PROCESSING AFTER FILTERING MISSING / MALFORMED REPOS
│───────────────────│────────────────────────────────────────────────────│
│ REPO NAME │ REPO URL │
│───────────────────│────────────────────────────────────────────────────│
│ terraform-aws-vpc │ https://github.com/zack-test-org/terraform-aws-vpc │
│ terraform-aws-eks │ https://github.com/zack-test-org/terraform-aws-eks │
│ circleci-test-1 │ https://github.com/zack-test-org/circleci-test-1 │
│───────────────────│────────────────────────────────────────────────────│
REPOS THAT WERE SUCCESSFULLY CLONED TO THE LOCAL FILESYSTEM
│───────────────────│────────────────────────────────────────────────────│
│ REPO NAME │ REPO URL │
│───────────────────│────────────────────────────────────────────────────│
│ terraform-aws-eks │ https://github.com/zack-test-org/terraform-aws-eks │
│ circleci-test-1 │ https://github.com/zack-test-org/circleci-test-1 │
│ terraform-aws-vpc │ https://github.com/zack-test-org/terraform-aws-vpc │
│───────────────────│────────────────────────────────────────────────────│
REPOS THAT SHOWED FILE CHANGES TO THEIR WORKING DIRECTORY FOLLOWING COMMAND EXECUTION
│───────────────────│────────────────────────────────────────────────────│
│ REPO NAME │ REPO URL │
│───────────────────│────────────────────────────────────────────────────│
│ terraform-aws-eks │ https://github.com/zack-test-org/terraform-aws-eks │
│ terraform-aws-vpc │ https://github.com/zack-test-org/terraform-aws-vpc │
│ circleci-test-1 │ https://github.com/zack-test-org/circleci-test-1 │
│───────────────────│────────────────────────────────────────────────────│
REPOS THAT WERE SUPPLIED BY USER BUT DON'T EXIST (404'D) VIA GITHUB API
│────────────────────────│──────────│
│ REPO NAME │ REPO URL │
│────────────────────────│──────────│
│ terraform-aws-asg │ │
│ terraform-aws-security │ │
│────────────────────────│──────────│
REPOS WHOSE SPECIFIED BRANCHES DID NOT EXIST ON THE REMOTE, AND SO WERE FIRST CREATED LOCALLY
│───────────────────│────────────────────────────────────────────────────│
│ REPO NAME │ REPO URL │
│───────────────────│────────────────────────────────────────────────────│
│ terraform-aws-eks │ https://github.com/zack-test-org/terraform-aws-eks │
│ terraform-aws-vpc │ https://github.com/zack-test-org/terraform-aws-vpc │
│ circleci-test-1 │ https://github.com/zack-test-org/circleci-test-1 │
│───────────────────│────────────────────────────────────────────────────│
*****************************************************
PULL REQUESTS OPENED
*****************************************************
│───────────────────│────────────────────────────────────────────────────────────│
│ REPO NAME │ PR URL │
│───────────────────│────────────────────────────────────────────────────────────│
│ circleci-test-1 │ https://github.com/zack-test-org/circleci-test-1/pull/82 │
│ terraform-aws-eks │ https://github.com/zack-test-org/terraform-aws-eks/pull/81 │
│ terraform-aws-vpc │ https://github.com/zack-test-org/terraform-aws-vpc/pull/77 │
│───────────────────│────────────────────────────────────────────────────────────│
If you are Homebrew user, you can install by running
$ brew install git-xargs
Download the correct binary for your platform. Visit the releasespage and download the correct binary depending on your system.Save it to somewhere on your PATH
, such as /usr/local/bin/git-xargs
.
Set execute permissions. For example, on Linux or Mac, you'd run:
chmod u+x /usr/local/bin/git-xargs
Check it's working. Run the version command to ensure everything is working properly:
git-xargs --version
Ensure you have Golang installed and working properly on your system. Follow the official Golang install guide to get started.
Run go get to install the latest release of git-xargs:
go get github.com/gruntwork-io/git-xargs
Alternatively, use go get to install a specific release of git-xargs:
go get github.com/gruntwork-io/git-xargs@v0.0.5
Export a valid GitHub token. See the guide on Github personal accesstokensfor information on how to generate one. For example, on Linux or Mac, you'd run:
export GITHUB_OAUTH_TOKEN=<your-secret-github-oauth-token>
Provide a script or command and target some repos. Here's a simple example of running the touch
command inevery repo in your GitHub organization. Follow the same pattern to start running your own scripts and commandsagainst your own repos!
git-xargs \
--branch-name "test-branch" \
--commit-message "Testing git-xargs" \
--github-org <enter-your-github-org-name> \
touch git-xargs-is-awesome.txt
The API for git-xargs
is:
git-xargs [-flags] <CMD>
Where CMD
is either the full path to a (Bash, Python, Ruby, etc) script on your local system or a binary. Note that, because the tool supports Bash scripts, Ruby scripts, Python scripts, etc, you must include the full filename for any given script, including its file extension.
In other words, all the following usages are valid:
git-xargs --repo gruntwork-io/cloud-nuke \
--repo gruntwork-io/terraform-aws-eks \
--branch-name my-branch \
/usr/local/bin/my-bash-script.sh
git-xargs --repos ./my-repos.txt \
--branch-name my-other-branch \
touch file1.txt file2.txt
git-xargs --github-org my-github-org \
--branch-name my-new-branch \
"$(pwd)/scripts/my-ruby-script.rb"
By default, git-xargs
will conceal runtime errors as they occur because its log level setting is INFO
if not overridden by the --loglevel
flag.
To see all errors your script or command may be generating, be sure to pass --loglevel DEBUG
when running your git-xargs
command, like so:
git-xargs --loglevel DEBUG \
--repo zack-test-org/terraform-aws-eks \
--branch-name master \
--commit-message "add blank file" \
--skip-pull-requests touch foo.txt
When the log level is set to debug
you should see new error output similar to the following:
Total 195 (delta 159), reused 27 (delta 11), pack-reused 17 Repo=terraform-aws-eks
[git-xargs] DEBU[2021-06-29T12:11:31-04:00] Created branch Branc
h Name=refs/heads/master Repo=terraform-aws-eks
[git-xargs] DEBU[2021-06-29T12:11:31-04:00] Error creating new branch Error
="a branch named \"refs/heads/master\" already exists" Repo=terraform-aws-eks
[git-xargs] DEBU[2021-06-29T12:11:31-04:00] Error encountered while processing repo Error
="a branch named \"refs/heads/master\" already exists" Repo name=terraform-aws-eks
Passing the --branch-name
(-b
) flag is required when running git-xargs
. If you specify the name of a branch that exists on your remote, its latest changes will be pulled locally prior to your command or script being run. If you specify the name of a new branch that does not yet exist on your remote, it will be created locally and pushed once your changes are committed.
Any pull requests opened will be opened against the repository's default branch (whether that's main
, or master
or something else).
Currently, git-xargs
will find and add any and all new files, as well as any existing files that were modified, within your repo and stage them prior to committing. If your script or command creates a new file, it will be committed. If your script or command edits an existing file, that change will also be committed.
Scripts may be placed anywhere on your system, but you are responsible for providing absolute paths to your scripts when invoking git-xargs
:
git-xargs \
--branch-name upgrade-tf-14 \
--commit-message "Update modules to Terraform 0.14" \
--repos data/batch3.txt \
$(pwd)/scripts/my-ruby-script.rb
or
git-xargs \
--branch-name upgrade-tf-14 \
--commit-message "Update modules to Terraform 0.14" \
--repos data/batch3.txt \
/usr/local/bin/my-ruby-script.rb
If you need to compose more complex behavior into a single pull request, write a wrapper script that executes all your commands, or place all your logic into one script.
git-xargs
supports four methods of targeting repos to run your selected scripts against. They are processed inthe order listed below, with whichever option is found first being used, and all others after it being ignored.
If you want the tool to find and select every repo in your GitHub organization, you can pass the name of your organization via the --github-org
flag:
git-xargs \
--commit-message "Update copyright year" \
--github-org <your-github-org> \
"$(pwd)/scripts/update-copyright-year.sh"
This will signal the tool to look up, and page through, every repository in your GitHub organization and execute the scripts you passed.
Oftentimes, you want finer-grained control over the exact repos you are going to run your script against. In this case, you can use the --repos
flag and supply the path to a file defining the exact repos you want the tool to run your selected scripts against, like so:
git-xargs \
--commit-mesage "Update copyright year" \
--repos data/batch2.txt \
"$(pwd)/scripts/update-copyright-year.sh"
In this example, batch2.txt looks like this:
gruntwork-io/infrastructure-as-code-training
gruntwork-io/infrastructure-live-acme
gruntwork-io/infrastructure-live-multi-account-acme
gruntwork-io/infrastructure-modules-acme
gruntwork-io/infrastructure-modules-multi-account-acme
Flat files contain one repo per line, each repository in the format of <github-organization>/<repo-name>
. Commas, trailing or preceding spaces, and quotes are all filtered out at runtime. This is done in case you end up copying your repo list from a JSON list or CSV file.
Another way to get fine-grained control is to pass in the individual repos you want to use via one or more --repo
arguments:
git-xargs \
--commit-mesage "Update copyright year" \
--repo gruntwork-io/terragrunt \
--repo gruntwork-io/terratest \
--repo gruntwork-io/cloud-nuke \
"$(pwd)/scripts/update-copyright-year.sh"
And one more (Unix-philosophy friendly) way to get fine-grained control is to pass in the individual repos you want touse by piping them in via stdin
, separating repo names with whitespace or newlines:
echo "gruntwork-io/terragrunt gruntwork-io/terratest" | git-xargs \
--commit-mesage "Update copyright year" \
"$(pwd)/scripts/update-copyright-year.sh"
git-xargs
exposes several flags that allow you to customize its behavior to better suit your needs. For the latest info on flags, you should run git-xargs --help
. However, a couple of the flags are worth explaining more in depth here:
Flag | Description | Type | Required |
---|---|---|---|
--branch-name |
You must specify the name of the branch to make your local and remote changes on. You can further control branching behavior via --skip-pull-requests as explained below |
String | Yes |
--loglevel |
Specify the log level of messages git-xargs should print to STDOUT at runtime. By default, this is INFO - so only INFO level messages will be visible. Pass DEBUG to see runtime errors encountered by your scripts or commands. Accepted levels are TRACE, DEBUG, INFO, WARNING, ERROR, FATAL and PANIC. Default: INFO . |
String | No |
--repos |
If you want to specify many repos and manage them in files (which makes batching and testing easier) then use this flag to pass the filepath to a repos file. See the repos file format for more information | String | No |
--repo |
Use this flag to specify a single repo, e.g., --repo gruntwork-io/cloud-nuke . Can be passed multiple times to target several repos |
String | No |
--github-org |
If you want to target every repo in a Github org that your GITHUB_OAUTH_TOKEN has access to, pass the name of the Organization with this flag, to page through every repo via the Github API and target it | String | No |
--commit-message |
The commit message to use when creating commits. If you supply this flag, but neither the optional --pull-request-title or --pull-request-description flags, then the commit message value will be used for all three. |
String | No |
--skip-pull-requests |
If you don't want any pull requests opened, but would rather have your changes committed directly to your specified branch, pass this flag. Note that it won't work if your Github repo is configured with branch protections on the branch you're trying to commit directly to! | Boolean | No |
--skip-archived-repos |
If you want to exclude archived (read-only) repositories from the list of targeted repos, pass this flag. | Boolean | No |
--dry-run |
If you are in the process of testing out git-xargs or your initial set of targeted repos, but you don't want to make any changes via the Github API (pushing your local changes or opening pull requests) you can pass the dry-run flag. This is useful because the output report will still tell you which repos would have been affected, without actually making changes via the Github API to your remote repositories. |
Boolean | No |
--max-concurrent-repos |
Limits the number of concurrent processed repositories. This is only useful if you encounter issues and need throttling when running on a very large number of repos. Default is 0 (Unlimited) |
Integer | No |
Write your script as if it's operating on a single repo, then target many repos with git-xargs
. Remember that at runtime, each of the scripts you select will be run, in the order you specify, once per repo that you've targeted.
It is currently assumed that bash script authors will be responsible for checking for prerequisites within their own scripts. If you are adding a new bash script to accomplish some new task across repos, consider using the Gruntwork bash-commons assert_is_installed pattern to ensure the operator has any required binaries installed.
This is a pattern that ended up working out well for us as we wrote and executed more and more ambitious scripts across our many repos as a team:By breaking your target repos into separate batches, (batch1.txt, batch2.txt, batch3.txt) and starting with a few repos (or even one repo!) in the initial batches, and then gradually expanding the batches in size, you can easily test your new scripts against a few repos and double check the generated pull requests for any issues prior to widening your target batches.
This section provides a more in-depth look at how the git-xargs
tool works under the hood.
/tmp/
directory of your local machine. The name of each repo, plus a random number each run, are concatenated together to form the local clone name to make the local repo easier to find in case you need to debug your script locally, e.g., terraform-aws-module-security3978298
.--branch-name
flag)--commit-message
flag)--pull-request-title
and --pull-request-description
flags, respectively, unless you pass the --skip-pull-requests
flagThe following is a non-exhaustive list of potential use cases for git-xargs
:
.circleci/config.yml
file in each repo using a tool such as yq
sed
commands to update or replace information across README filespackage.json
files in-place across repos to bump a node.js dependency using jq
https://stedolan.github.io/jq/find
and its exec
optiongo get
to install and uninstall packages, and modify the source code files' import referencesIf you can instrument the logic in a script, you can use git-xargs
to run it across your repos!
We hope that this tool will help save you some time as you apply it to your own automations and maintenance tasks. We also welcome the community to contribute back scripts that everyone can use and benefit from.
Initially, we'll add these scripts to the ./scripts
directory in this repository and will eventually organize them into sub-folders depending on their purposes / use cases. If you would like to have your script considered for inclusion in this repo, please first ensure that it is:
Once you've done this, please feel free to open a pull request adding your script to the ./scripts
directory for consideration.
Thanks for contributing back! Our hope is that eventually this repo will contain many useful generic scripts for common maintenance and upgrading tasks that everyone can leverage to save time.
Clone this repository and then run the following command from the root of the repository:
go build
The git-xargs
binary will be present in the repository root.
Alternatively, you can run the tool directly without building the binary, like so:
./go run main.go \
--branch-name test-branch \
--commit-message "Add MIT License" \
--repos data/test-repos.txt \
$(pwd)/scripts/add-license.sh
This is especially helpful if you are developing against the tool and want to quickly verify your changes.
Tests are included within their respective packages.
go test -v ./...
This code is released under the Apache 2.0 License. See LICENSE.txt
Git branch 常用参数解释 git branch 不仅仅可以用来创建删除分支,当它不加任何参数的时候,会得到当前所有分支的一个列表,带有* 号的表示HEAD所指向的分支。 git branch -v 可以列出每一个分支的最后一次提交。 git branch --merged可以查看哪些分支已经合并到当前分支,此列表下没有* 标记的分支可以删除,不会报错。 git branch --no-m
问: git add [–all | -A] 和 git add . 有什么区别? huntsbot.com – 高效赚钱,自由工作 答1: huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。 此答案仅适用于 Git 版本 1.x。对于 Git 版本 2.x,请参阅其他答案。 概括: git add -A 阶段所有更改 混帐添加。暂存新文件和修改
1.查看自己提交的代码量 git log --since="2018-08-13" --before="2018-08-14" --author="$(git config --get user.name)" --pretty=tformat: --numstat | gawk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "a
git-ls-files - 显示有关索引和工作树中文件的信息 概要 git ls-files [-z] [-t] [-v] [-f] (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])* (-[c|d|o|i|s|u|k|m])* [--eol] [-x <pattern>|--exclude=<
1.添加标签: git tag <tagName> //创建本地tag git push origin <tagName> //推送到远程仓库 git tag -a version -m "note" 注解:git tag 是打标签的命令,-a 是添加标签,其后要跟新标签号,-m 及后面的字符串是对该标签的注释。 2.提交标签到远程仓库 : git push origin -tags 若存在很多
git-repo简介 git-repo简称Repo,是google为了方便管理多个git库而开发的Python脚本; repo本身依赖git(建议1.9以上)和python(3.5以上版本); 实际在Android开发或高通芯片sdk开发中,经常使用这种机制来下载源代码。 安装过程 下载repo [qxhgd@localhost git-repo]$ curl https://mirrors.tu
git status -s 状态码 M = 修改 > 文件的内容或者mode被修改了. A = 已添加 > 你本地新增的文件(服务器上文件没有新增) D = 已删除 > 本地删除的文件(服务器上文件还在). R = 重命名 > 文件名被修改 C = 复制 > 文件的一个拷贝 U = 已更新但尚未装入 > 文件没有被合并(需要完成合并才能进行提交) T = 文件的类型被修改了 > 文件的类型被修改
名称NAME git-stash - 将在脏的工作目录中的更改暂存起来 概要SYNOPSIS git stash list [<options>] git stash show [<options>] [<stash>] git stash drop [-q|--quiet] [<stash>] git stash ( pop | apply ) [--index] [-q|--quiet] [<
前言 Git 是一个分布式版本管理工具,版本管理工具就是大家在写东西的时候都用过 回撤这个功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用回撤是找不回来的。而版本管理工具能记录每次的修改,只要提交到版本仓库,就可以找到之前任何时刻的状态(文本状态)。 下面的内容就是列举了常用的 Git 命令和一些小技巧,可以通过页面内查找的方式 Ctrl/Command+f 进行快速查找。 1.展示
1.查看上传日志 git log 2.查看本地修改的文件 git diff 3.查看本地修改的文件列表(这个实用) git diff --name-only 4.查看本地文件状态,包括未跟踪的文件(没有add的新增文件)(实用) git status 5.增加本地文件commit git add 6.提交本地文件 git commit 7.上传提交的文件 git push 8.查看修改记录和该记录
git diff --name-only commitId commitId | xargs tar -zcvf 1.tar.gz 两个commitId 第一个是之前的版本id 第二个是当前的版本id 对比两个版本的差异并压缩成1.tar.gz
创建一个新文件 ~/.gitignore ,并将以下内容添加进去,这样全部 git 仓库将会忽略以下内容所提及的文件。 # Folder view configuration files .DS_Store Desktop.ini # Thumbnail cache files ._* Thumbs.db # Files that might appear on external disks .S
功能分支(feature branches)、发布分支(release branches)、主干(master)、开发分支(develop)、紧急修复分支(hotfixes)和标签(tag)。 Git Flow 太复杂 Git Flow 违背了分支的“短命”原则:在使用 Git 时,在同一个分支上开发代码的人越多,出现合并冲突的几率就越高。在使用 Git Flow 后,冲突几率会变得更高,因为还有
规范建设 commit message格式 <type>(<scope>): <subject> type(必须) 用于说明git commit的类别,只允许使用下面的标识。 feat:新功能(feature)。 fix/to:修复bug,可以是QA发现的BUG,也可以是研发自己发现的BUG。 fix:产生diff并自动修复此问题。适合于一次提交直接修复问题 to:只产生diff不自动修复此问题
集中式与分布式 中心服务器 工作流 分支实现 冲突 Fast forward 储藏(Stashing) SSH 传输设置 .gitignore 文件 Git 命令一览 参考资料 集中式与分布式 Git 属于分布式版本控制系统,而 SVN 属于集中式。 集中式版本控制只有中心服务器拥有一份代码,而分布式版本控制每个人的电脑上就有一份完整的代码。 集中式版本控制有安全性问题,当中心服务器挂了所有人都没
作为一名开发者怎么可能没有 Git 呢? 我们马上就来安装: $ brew install git 好的,现在我们来测试一下 git 是否安装完好: $ git --version 运行 $ which git 将会输出 /usr/local/bin/git. 接着,我们将定义你的 Git 帐号(与你在 GitHub 使用的用户名和邮箱一致) $ git config --global user.
Name git - 迟钝的内容跟踪器 概要 git [--version] [--help] [-C <path>] [-c <name>=<value>] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects]