From 1293c023c960a4f0225c8e3194373b1563337536 Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Mon, 4 Nov 2024 18:36:32 -0600 Subject: [PATCH 1/7] Add base group scripts. --- .tools/git_group_functions.sh | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .tools/git_group_functions.sh diff --git a/.tools/git_group_functions.sh b/.tools/git_group_functions.sh new file mode 100644 index 0000000..714fd9e --- /dev/null +++ b/.tools/git_group_functions.sh @@ -0,0 +1,51 @@ +# Function to check if a directory is a Git repository +is_git_repo() { + git -C "$1" rev-parse --is-inside-work-tree &>/dev/null +} + +git_nested() { + search_dir="$1" + + echo -e "=== Running ${@:2} ==="; + + # Find all .git directories and run the command in their parent directories + find "$search_dir" -type d -name ".git" | while read -r git_dir; do + repo_dir=$(dirname "$git_dir") + + remote_url_string=$(git -C "$repo_dir" remote show origin | grep Fetch); + + # Check if the string does NOT contain "repository-group" + echo $remote_url_string | grep -q "repository-group" + not_repository_group=$? + + # If grep finds the string, it will return 0. So we check if it's not equal to 0 + if is_git_repo "$repo_dir" && [ $not_repository_group -ne 0 ]; then + echo $repo_dir: + git -C "$repo_dir" ${@:2} + fi + done +} + +git_nested_delete_merged_branches() { + search_dir="$1" + + echo -e "=== Removing merged branches ==="; + + # Find all .git directories and run the command in their parent directories + find "$search_dir" -type d -name ".git" | while read -r git_dir; do + repo_dir=$(dirname "$git_dir") + + remote_url_string=$(git -C "$repo_dir" remote show origin | grep Fetch); + + # Check if the string does NOT contain "repository-group" + echo $remote_url_string | grep -q "repository-group" + not_repository_group=$? + + # If grep finds the string, it will return 0. So we check if it's not equal to 0 + if is_git_repo "$repo_dir" && [ $not_repository_group -ne 0 ]; then + echo $repo_dir: + 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 +} + From a7a0ab29cd4b39391a5452c39e926868cb462e74 Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Tue, 12 Nov 2024 19:40:54 -0600 Subject: [PATCH 2/7] Get recursive git working. --- .tools/git_group_functions.sh | 50 ++++++----------------------------- .tools/recursive_git.sh | 4 +++ 2 files changed, 12 insertions(+), 42 deletions(-) create mode 100755 .tools/recursive_git.sh diff --git a/.tools/git_group_functions.sh b/.tools/git_group_functions.sh index 714fd9e..686d2a7 100644 --- a/.tools/git_group_functions.sh +++ b/.tools/git_group_functions.sh @@ -3,49 +3,15 @@ is_git_repo() { git -C "$1" rev-parse --is-inside-work-tree &>/dev/null } -git_nested() { - search_dir="$1" +recursive_git() { + repo_dirs=($(find "$(pwd)" -type d -name ".git" -exec dirname {} \;)) + repo_dirs=($(for i in "${repo_dirs[@]}"; do echo "$i"; done | sort)) - echo -e "=== Running ${@:2} ==="; - - # Find all .git directories and run the command in their parent directories - find "$search_dir" -type d -name ".git" | while read -r git_dir; do - repo_dir=$(dirname "$git_dir") - - remote_url_string=$(git -C "$repo_dir" remote show origin | grep Fetch); - - # Check if the string does NOT contain "repository-group" - echo $remote_url_string | grep -q "repository-group" - not_repository_group=$? - - # If grep finds the string, it will return 0. So we check if it's not equal to 0 - if is_git_repo "$repo_dir" && [ $not_repository_group -ne 0 ]; then - echo $repo_dir: - git -C "$repo_dir" ${@:2} - fi - done -} - -git_nested_delete_merged_branches() { - search_dir="$1" - - echo -e "=== Removing merged branches ==="; - - # Find all .git directories and run the command in their parent directories - find "$search_dir" -type d -name ".git" | while read -r git_dir; do - repo_dir=$(dirname "$git_dir") - - remote_url_string=$(git -C "$repo_dir" remote show origin | grep Fetch); - - # Check if the string does NOT contain "repository-group" - echo $remote_url_string | grep -q "repository-group" - not_repository_group=$? - - # If grep finds the string, it will return 0. So we check if it's not equal to 0 - if is_git_repo "$repo_dir" && [ $not_repository_group -ne 0 ]; then - echo $repo_dir: - 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 + for repo_dir in "${repo_dirs[@]}"; do + if is_git_repo "$repo_dir"; then + relative_repo_dir=$(realpath --relative-to="$(pwd)" "$repo_dir") + echo "git -C $relative_repo_dir ${@:1}" + git -C "$relative_repo_dir" ${@:1} fi done } - diff --git a/.tools/recursive_git.sh b/.tools/recursive_git.sh new file mode 100755 index 0000000..80f1737 --- /dev/null +++ b/.tools/recursive_git.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source "$(dirname "$0")/git_group_functions.sh" +recursive_git "$@" From 22fbad826c332d173c601d1099d590a6eb63c363 Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Tue, 12 Nov 2024 19:54:40 -0600 Subject: [PATCH 3/7] Add reset branch function, delete merged branches function. --- .tools/git_group_functions.sh | 15 +++++++++++++++ .tools/recursive_git_delete_merged_branches.sh | 4 ++++ .tools/recursive_git_reset_branch.sh | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100755 .tools/recursive_git_delete_merged_branches.sh create mode 100755 .tools/recursive_git_reset_branch.sh diff --git a/.tools/git_group_functions.sh b/.tools/git_group_functions.sh index 686d2a7..93205a1 100644 --- a/.tools/git_group_functions.sh +++ b/.tools/git_group_functions.sh @@ -15,3 +15,18 @@ recursive_git() { fi done } + +# Not sure how to share the common code between these two +recursive_git_delete_merged_branches() { + repo_dirs=($(find "$(pwd)" -type d -name ".git" -exec dirname {} \;)) + repo_dirs=($(for i in "${repo_dirs[@]}"; do echo "$i"; done | sort)) + + for repo_dir in "${repo_dirs[@]}"; do + if is_git_repo "$repo_dir"; then + relative_repo_dir=$(realpath --relative-to="$(pwd)" "$repo_dir") + echo "git -C $relative_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 "$relative_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/recursive_git_delete_merged_branches.sh b/.tools/recursive_git_delete_merged_branches.sh new file mode 100755 index 0000000..b42ed7d --- /dev/null +++ b/.tools/recursive_git_delete_merged_branches.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source "$(dirname "$0")/git_group_functions.sh" +recursive_git_delete_merged_branches diff --git a/.tools/recursive_git_reset_branch.sh b/.tools/recursive_git_reset_branch.sh new file mode 100755 index 0000000..36b3d26 --- /dev/null +++ b/.tools/recursive_git_reset_branch.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +source "$(dirname "$0")/git_group_functions.sh" + +recursive_git fetch --all --prune +recursive_git checkout develop +recursive_git reset --hard +recursive_git pull +recursive_git fetch --all --prune + +recursive_git_delete_merged_branches + +if [ "$1" != "develop" ]; then + recursive_git checkout $1 + recursive_git reset --hard + recursive_git pull + recursive_git rebase develop +fi From e8a68388d167c80f79c5980297860ec4c15cd6cc Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Tue, 12 Nov 2024 19:56:13 -0600 Subject: [PATCH 4/7] Remove extra prune. --- .tools/recursive_git_reset_branch.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.tools/recursive_git_reset_branch.sh b/.tools/recursive_git_reset_branch.sh index 36b3d26..8c756ff 100755 --- a/.tools/recursive_git_reset_branch.sh +++ b/.tools/recursive_git_reset_branch.sh @@ -6,7 +6,6 @@ recursive_git fetch --all --prune recursive_git checkout develop recursive_git reset --hard recursive_git pull -recursive_git fetch --all --prune recursive_git_delete_merged_branches From 0f3e3c7d6a8d4ca65914f8e73f497483af99effc Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Wed, 13 Nov 2024 10:42:34 -0600 Subject: [PATCH 5/7] Cleanup naming and code. --- .tools/common_git_functions.sh | 42 +++++++++++++++++++ .tools/git_group_functions.sh | 32 -------------- .tools/git_recursive.sh | 4 ++ .../git_recursive_delete_merged_branches.sh | 4 ++ .tools/git_recursive_reset_branch.sh | 17 ++++++++ .tools/recursive_git.sh | 4 -- .../recursive_git_delete_merged_branches.sh | 4 -- .tools/recursive_git_reset_branch.sh | 17 -------- 8 files changed, 67 insertions(+), 57 deletions(-) create mode 100644 .tools/common_git_functions.sh delete mode 100644 .tools/git_group_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 delete mode 100755 .tools/recursive_git.sh delete mode 100755 .tools/recursive_git_delete_merged_branches.sh delete mode 100755 .tools/recursive_git_reset_branch.sh diff --git a/.tools/common_git_functions.sh b/.tools/common_git_functions.sh new file mode 100644 index 0000000..f7f6f67 --- /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\" ${@:1}" + git -C "$repo_dir" ${@:1} + 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_group_functions.sh b/.tools/git_group_functions.sh deleted file mode 100644 index 93205a1..0000000 --- a/.tools/git_group_functions.sh +++ /dev/null @@ -1,32 +0,0 @@ -# Function to check if a directory is a Git repository -is_git_repo() { - git -C "$1" rev-parse --is-inside-work-tree &>/dev/null -} - -recursive_git() { - repo_dirs=($(find "$(pwd)" -type d -name ".git" -exec dirname {} \;)) - repo_dirs=($(for i in "${repo_dirs[@]}"; do echo "$i"; done | sort)) - - for repo_dir in "${repo_dirs[@]}"; do - if is_git_repo "$repo_dir"; then - relative_repo_dir=$(realpath --relative-to="$(pwd)" "$repo_dir") - echo "git -C $relative_repo_dir ${@:1}" - git -C "$relative_repo_dir" ${@:1} - fi - done -} - -# Not sure how to share the common code between these two -recursive_git_delete_merged_branches() { - repo_dirs=($(find "$(pwd)" -type d -name ".git" -exec dirname {} \;)) - repo_dirs=($(for i in "${repo_dirs[@]}"; do echo "$i"; done | sort)) - - for repo_dir in "${repo_dirs[@]}"; do - if is_git_repo "$repo_dir"; then - relative_repo_dir=$(realpath --relative-to="$(pwd)" "$repo_dir") - echo "git -C $relative_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 "$relative_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..4012d3a --- /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/.tools/recursive_git.sh b/.tools/recursive_git.sh deleted file mode 100755 index 80f1737..0000000 --- a/.tools/recursive_git.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -source "$(dirname "$0")/git_group_functions.sh" -recursive_git "$@" diff --git a/.tools/recursive_git_delete_merged_branches.sh b/.tools/recursive_git_delete_merged_branches.sh deleted file mode 100755 index b42ed7d..0000000 --- a/.tools/recursive_git_delete_merged_branches.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -source "$(dirname "$0")/git_group_functions.sh" -recursive_git_delete_merged_branches diff --git a/.tools/recursive_git_reset_branch.sh b/.tools/recursive_git_reset_branch.sh deleted file mode 100755 index 8c756ff..0000000 --- a/.tools/recursive_git_reset_branch.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -source "$(dirname "$0")/git_group_functions.sh" - -recursive_git fetch --all --prune -recursive_git checkout develop -recursive_git reset --hard -recursive_git pull - -recursive_git_delete_merged_branches - -if [ "$1" != "develop" ]; then - recursive_git checkout $1 - recursive_git reset --hard - recursive_git pull - recursive_git rebase develop -fi From 05f3c71329a7882d1b7a3fb3fd0ef64d8c469a69 Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Wed, 13 Nov 2024 10:44:33 -0600 Subject: [PATCH 6/7] Fix bash warnings. --- .tools/common_git_functions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.tools/common_git_functions.sh b/.tools/common_git_functions.sh index f7f6f67..c01ea9c 100644 --- a/.tools/common_git_functions.sh +++ b/.tools/common_git_functions.sh @@ -20,8 +20,8 @@ git_recursive() { for repo_dir in "${repo_dirs[@]}"; do if is_git_repo "$repo_dir"; then - echo "git -C \"$repo_dir\" ${@:1}" - git -C "$repo_dir" ${@:1} + echo "git -C \"$repo_dir\" $*" + git -C "$repo_dir" "$@" fi done } From 87d0ab71444e032101ef4f8f8fe00cfed0c62bfb Mon Sep 17 00:00:00 2001 From: Duncan Calvert Date: Wed, 13 Nov 2024 10:58:10 -0600 Subject: [PATCH 7/7] Add README, address bash warning. --- .tools/git_recursive_reset_branch.sh | 2 +- README.md | 41 ++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.tools/git_recursive_reset_branch.sh b/.tools/git_recursive_reset_branch.sh index 4012d3a..82fdeae 100755 --- a/.tools/git_recursive_reset_branch.sh +++ b/.tools/git_recursive_reset_branch.sh @@ -10,7 +10,7 @@ git_recursive pull git_recursive_delete_merged_branches if [ "$1" != "develop" ]; then - git_recursive checkout $1 + git_recursive checkout "$1" git_recursive reset --hard git_recursive pull git_recursive rebase develop 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)