From 3d30f3722955129030d219d63dffa9ea83292a63 Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Wed, 13 Nov 2024 11:05:30 -0600 Subject: [PATCH] Add recursive git scripts. (#7) --- .tools/common_git_functions.sh | 42 +++++++++++++++++++ .tools/git_recursive.sh | 4 ++ .../git_recursive_delete_merged_branches.sh | 4 ++ .tools/git_recursive_reset_branch.sh | 17 ++++++++ README.md | 41 ++++++++++++++---- 5 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 .tools/common_git_functions.sh create mode 100755 .tools/git_recursive.sh create mode 100755 .tools/git_recursive_delete_merged_branches.sh create mode 100755 .tools/git_recursive_reset_branch.sh diff --git a/.tools/common_git_functions.sh b/.tools/common_git_functions.sh new file mode 100644 index 0000000..c01ea9c --- /dev/null +++ b/.tools/common_git_functions.sh @@ -0,0 +1,42 @@ +# Function to check if a directory is a Git repository +is_git_repo() { + git -C "$1" rev-parse --is-inside-work-tree &>/dev/null +} + +find_repo_dirs() { + # 1. Recursively find .git folders. + # 2. Remove the /.git from path. + # 3. Make the path relative. + # 4. Sort paths alphabetically. + find "$(pwd)" -type d -name ".git" -print0 \ + | xargs -0 -I {} dirname {} \ + | xargs -I {} realpath --relative-to="$(pwd)" {} \ + | sort +} + +# Recursively runs git commands on all git repos in a directory +git_recursive() { + mapfile -t repo_dirs < <(find_repo_dirs) + + for repo_dir in "${repo_dirs[@]}"; do + if is_git_repo "$repo_dir"; then + echo "git -C \"$repo_dir\" $*" + git -C "$repo_dir" "$@" + fi + done +} + +# Deletes branches that used to have a matching ref on the remote, but it has +# been deleted. This happens when PRs are merged. +# (Not sure how to share the common code with the above) +git_recursive_delete_merged_branches() { + mapfile -t repo_dirs < <(find_repo_dirs) + + for repo_dir in "${repo_dirs[@]}"; do + if is_git_repo "$repo_dir"; then + echo "git -C \"$repo_dir\" for-each-ref --format '%(refname:short) %(upstream:track)' | awk '\$2 == "[gone]" {print \$1}' | xargs -r git -C \"$repo_dir\" branch -D" + git -C "$repo_dir" for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git -C "$repo_dir" branch -D + fi + done +} + diff --git a/.tools/git_recursive.sh b/.tools/git_recursive.sh new file mode 100755 index 0000000..df04a3c --- /dev/null +++ b/.tools/git_recursive.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source "$(dirname "$0")/common_git_functions.sh" +git_recursive "$@" diff --git a/.tools/git_recursive_delete_merged_branches.sh b/.tools/git_recursive_delete_merged_branches.sh new file mode 100755 index 0000000..6c930b2 --- /dev/null +++ b/.tools/git_recursive_delete_merged_branches.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source "$(dirname "$0")/common_git_functions.sh" +git_recursive_delete_merged_branches diff --git a/.tools/git_recursive_reset_branch.sh b/.tools/git_recursive_reset_branch.sh new file mode 100755 index 0000000..82fdeae --- /dev/null +++ b/.tools/git_recursive_reset_branch.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +source "$(dirname "$0")/common_git_functions.sh" + +git_recursive fetch --all --prune +git_recursive checkout develop +git_recursive reset --hard +git_recursive pull + +git_recursive_delete_merged_branches + +if [ "$1" != "develop" ]; then + git_recursive checkout "$1" + git_recursive reset --hard + git_recursive pull + git_recursive rebase develop +fi diff --git a/README.md b/README.md index da5be45..68c326c 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,39 @@ These files are compatible with projects that use the [ihmc-build](https://githu ### Starting from scratch +Use [repository-collections](https://github.com/ihmcrobotics/repository-collections) or build the repo structure manually: + - `git clone` this repository. - `cd repository-group` - `git clone` project repositories into it. -Normally, nesting Git repos inside of each other is frowned upon, but in this case, the .gitignore uses a whitelist instead of a blacklist, so your repos won't be affected by Git operations on repository-group. +Normally, nesting Git repos inside each other is frowned upon, but in this case, the .gitignore uses a whitelist instead of a blacklist, so your repos won't be affected by Git operations on repository-group. + +### Maintaining the workspace + +We provide recursive git scripts in the `.tools` directory to help keep your group up to date. + +``` +# Perform Git operation on all repos including this one +repository-group $ .tools/git_recursive.sh [git args ...] + +# Delete local branches after the PR has been merged. +repository-group $ .tools/git_recursive_delete_merged_branches.sh + +# Reset to a branch and rebase it with develop. +# WARNING: Discard local changes first! +# This checks out develop, pulls, fetches, +# checks out, and rebases your branch onto develop. +repository-group $ .tools/git_recursive_reset_branch.sh branch-name + +# Examples: + +# Fetch all repos +repository-group $ .tools/git_recursive.sh fetch --all + +# Start working on your feature and make sure you're up to date with develop +repository-group $ .tools/git_recursive_reset_branch.sh feature/improvements +``` ### Convert your existing folder to a repository-group @@ -28,10 +56,6 @@ git reset origin/develop --hard git branch --set-upstream-to origin/develop develop ``` -### Staying up to date - -`git pull` to update to the latest ihmc-build plugin. - ### Cleaning up build files Run `gradle cleanBuild --console=plain` to clean all `build/` (Gradle), `bin/` (Eclipse IDE), and `out/` (IntelliJ IDE) build directories. @@ -40,11 +64,11 @@ This sometimes helps to forces IDEs to recompile the code when state becomes inc ### Gradle install scripts -This repo contains helper scripts (in the `tools` directory) to install Gradle system-wide. There are installation scripts for both Linux (Ubuntu) and Windows. +This repo contains helper scripts (in the `.tools` directory) to install Gradle system-wide. There are installation scripts for both Linux (Ubuntu) and Windows. **Linux usage:** ``` -cd repository-group/tools +cd repository-group/.tools sudo bash installGradle-.sh ``` **Windows usage:**
@@ -55,5 +79,4 @@ Open a file explorer to the repository-group/tools directory. Right click on `in Support is provided through Github issues. Duncan Calvert (dcalvert@ihmc.org) - -**This repo is read-only. Do not attempt to push your changes!** +Dexton Anderson (danderson@ihmc.org)