pax_global_header00006660000000000000000000000064146504765620014531gustar00rootroot0000000000000052 comment=ec1d487312d6f20473b7eac94ef87d8bde422f8b git-subrepo-0.4.9/000077500000000000000000000000001465047656200140035ustar00rootroot00000000000000git-subrepo-0.4.9/.fish.rc000066400000000000000000000011531465047656200153400ustar00rootroot00000000000000#!fish #------------------------------------------------------------------------------ # # This is the `git-subrepo` initialization script. # # This script turns on the `git-subrepo` Git subcommand and its manpages, for # the *Fish* shell. # # Just add a line like this to your `~/.config/fish/config.fish`: # # source /path/to/git-subrepo/.fish.rc # #------------------------------------------------------------------------------ set GIT_SUBREPO_ROOT (dirname (realpath (status --current-filename))) set PATH $GIT_SUBREPO_ROOT/lib $PATH set -q MANPATH || set MANPATH '' set MANPATH $MANPATH $GIT_SUBREPO_ROOT/man git-subrepo-0.4.9/.gitattributes000066400000000000000000000000161465047656200166730ustar00rootroot00000000000000* text eol=lf git-subrepo-0.4.9/.github/000077500000000000000000000000001465047656200153435ustar00rootroot00000000000000git-subrepo-0.4.9/.github/workflows/000077500000000000000000000000001465047656200174005ustar00rootroot00000000000000git-subrepo-0.4.9/.github/workflows/test.yml000066400000000000000000000013451465047656200211050ustar00rootroot00000000000000name: Test on: push: branches: [ '*' ] pull_request: branches: [ '*' ] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v2 - if: startsWith(matrix.os, 'macos') run: brew install bash - run: git config --global user.email "you@example.com"; git config --global user.name "Your Name"; git config --global init.defaultBranch "master"; git config --global --add safe.directory "$PWD"; git config --global --add safe.directory "$PWD.git"; - if: startsWith(matrix.os, 'macos') run: make test - if: startsWith(matrix.os, 'ubuntu') run: make docker-tests git-subrepo-0.4.9/.gitignore000066400000000000000000000000131465047656200157650ustar00rootroot00000000000000/test/tmp/ git-subrepo-0.4.9/.rc000066400000000000000000000016031465047656200144100ustar00rootroot00000000000000# shellcheck shell=bash disable=2128 #------------------------------------------------------------------------------ # # This is the `git-subrepo` initialization script. # # This script turns on the `git-subrepo` Git subcommand, its manpages and TAB # completion for the *Bash* and *zsh* shells. # # Just add a line like this to your shell startup configuration: # # source /path/to/git-subrepo/.rc # #------------------------------------------------------------------------------ [[ -n ${ZSH_VERSION-} ]] && GIT_SUBREPO_ROOT=$0 || GIT_SUBREPO_ROOT=$BASH_SOURCE [[ $GIT_SUBREPO_ROOT =~ ^/ ]] || GIT_SUBREPO_ROOT=$PWD/$GIT_SUBREPO_ROOT GIT_SUBREPO_ROOT=$( cd "$(dirname "$GIT_SUBREPO_ROOT")" || return pwd ) || return export GIT_SUBREPO_ROOT export PATH=$GIT_SUBREPO_ROOT/lib:$PATH export MANPATH=$GIT_SUBREPO_ROOT/man:$MANPATH source "$GIT_SUBREPO_ROOT/share/enable-completion.sh" git-subrepo-0.4.9/Changes000066400000000000000000000144141465047656200153020ustar00rootroot00000000000000version: 0.4.9 date: Mon 25 Jul 2024 11:23:34 AM CST - Revert Fix bash-completion due to not being compatible with Windows --- version: 0.4.8 date: Mon 22 Jul 2024 07:40:00 AM CST - Remove all subrepo refs with clean --force - Allow the error() function to accept multiple arguments - Bug fixed where clone --force could change the tracked branch - Give a detailed error message if the parent SHA could not be found - Use the git configuration to determine the default branch name for the init command - Add --force to fetch command - Fix executable settings on installed files - Remove shebangs from library only files - Fix bash-completion for instances that used make install --- version: 0.4.7 date: Sun 7 Jul 2024 11:04:00 AM EST - Convert testing to use docker with updated git versions - Fix numerous places where quoting was incorrect causing path name collisions - Fix pull-force test to deal with git not defaulting to merges on pulls after 2.33 - Fix issue where docker tests didn't work with git 2.30 or higher because of increased permission scrutiny. - Update readme to say this tools is in production environments - Update readme to use internet archive for old articles about subrepo no longer available on their original source --- version: 0.4.6 date: Fri 21 Apr 2023 10:18:34 AM EST - Remove stale worktrees in the push command --- version: 0.4.5 date: Thu 22 Sep 2022 23:03:24 PM EST - Add --file option - Fix git subrepo status command for subrepos that share a common prefix. Closes #534. - Don't allow -b and --all - Fix documentation links - fix tests to support use of a default branch git config that is not "master" - pass --force to git add so a user's global .gitignore does not affect tests - Fix .rc and enable-completion.sh for zsh before 5.1 - Better format for options - The `fpath` variable is an array; expand correctly --- version: 0.4.3 date: Sat 21 Nov 2020 03:28:43 PM EST - Apply PR#511 to fix a 0.4.2 regression in zsh --- version: 0.4.2 date: Tue Nov 17 14:10:10 CST 2020 - Covert to GitHub Actions for testing - Add docker support to test multiple git/bash versions together - Require Bash 4.0+ - Use shellcheck as linter and address issues discovered - Discovered bug in git where @ is not a valid workspace name - Add --force command to subrepo pull - Now works with paths that contain spaces - Numerous documentation fixes - When two branches pointed to the same commit, we would sometimes pick the wrong branch. - ZSH completion fixes - Allow tests to run outside a git repo - Would not work if a different date format was set in git config - Address delay in filter-branch on newer versions of git - Display the git merge message on merge failure - Allow FISH integration on MacOS. - Add manpage support for FISH shell --- version: 0.4.1 date: Thu Jan 9 17:11:21 CST 2020 - Fix Bash version error messages and add to .rc - Nicer YAML formatting in .travis.yml - Wrap a long line - Update the docs - Force `make update` to always update docs - Don't use XXX in perl stuff - Add testing on MacOS - Remove conflicting -C from install -d commands. - Update version requirement documentation - Correct error message in branch - Use topo-order in subrepo branch - Make “git subrepo clean -f ...” delete refs correctly - Fix #410 Push empty repositories with recent git versions - Make subrepo work when run in a worktree - Simplify finding subrepos - Ask git to find the .gitrepo files - Doc: fix sentence repetition - Fix typos - Fixed typo - Travis CI not checking out a branch. --- version: 0.4.0 date: Thu Nov 8 12:26:38 CET 2018 changes: - Fix #325 Do not squash main repo commits - Improve error message for worktree handling - Make version checking portable. #307 - #307, improve version check - #307, update version requirement - Fix part #308, Add stderr output if commands fail - Fix #306: Add check to prevent following commits with no .gitrepo - Remove dry-run flag as it's not implemented. Make sure branch --force delete worktree - Fix #296, Replace --first-parent with --ancestry-path - Fix #291, specify Trusty host to get new 2.x git - Fix #258, add --no-tags to git fetch - Test that no remotes are created during clone - #257 Remove remote creation to avoid problems with fetch --all - (origin/issue/150_to_0.4.0) Fix remove-worktree, remove unused parameters - Regenerate completion files - filter-branch operation should not be done on HEAD - Cleanup push and add hint to push directly after pull - Simplify cleanup and add worktree to status - Add --method option to init/clone, add a 'config' command - Updated unit tests to support the new logic - Use 'git worktree' for merge/rebase - Update docs to reflect how things should work - Make it possible to specify commit messages - Redesign, trash the tree hash approach and use merges instead - Add release branches to travis-ci - Add --method option to init/clone, add a 'config' command - Detect multiple pulls, use -u flag to decide - Don't reuse previous commit message when using --all - Update the docs for pull and push - Update error messages when failing merge/rebase - Fix env var bug in test/push.t - Do not overwrite author information --- version: 0.3.1 date: Tue Jan 3 23:08:56 PST 2017 changes: - Updated release for homebrew - Fix #192 --- version: 0.3.0 date: Wed Dec 2 19:19:43 PST 2015 changes: - Fix issue #98 and host of others (89, 91, 95, 96) - Adds support for the merge-base command - Adds stability to many commands - Command completion updates - Rename `init` to `.rc` - @grimmySwe++ @dzzh++ @jrosdahl++ @perlpunk++ --- version: 0.2.3 date: Sun Aug 9 13:44:22 PDT 2015 changes: - Fix issues #75 and #76 --- version: 0.2.2 date: Wed Jul 22 09:45:13 PDT 2015 changes: - Added the `init` subcommand - Applied doc fixes --- version: 0.2.1 date: Sat Mar 28 07:52:22 PDT 2015 changes: - Allows subrepo clone to clone to an empty branch; fixes #26. - Refs in status - Empty parent set to 'none' in .gitrepo file. - Bug fixes --- version: 0.2.0 date: Sat Jan 24 06:22:05 PST 2015 changes: - Massive overhaul - .gitrepo files remain the same so backwards compatible - Introduce the branch and commit subcommands - The checkout subcommand goes away - Operations work much smoother like normal Git flow - Much more testing - Better doc --- version: 0.1.0 date: Fri Feb 21 12:25:53 2014 -0800 changes: - First version git-subrepo-0.4.9/Intro.pod000066400000000000000000000416051465047656200156100ustar00rootroot00000000000000=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.48. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 Introducing Git Subrepos There is a new git command called C that is meant to be a solid alternative to the C and C commands. All 3 of these commands allow you to include external repositories (pinned to specific commits) in your main repository. This is an often needed feature for project development under a source control system like Git. Unfortunately, the C command is severely lacking, and the C command (an attempt to make things better) is also very flawed. Fortunately, the C command is here to save the day. This article will discuss how the previous commands work, and where they go wrong, while explaining how the new C command fixes the issues. It should be noted that there are 3 distinct roles (ways people use repos) involved in discussing this topic: =over =item * B — The primary author and repo owner =item * B — Other developers who contribute to the repo =item * B — People who simply use the repo software =back =head2 Introducing C While the main point is to show how subrepo addresses the shortcomings of submodule and subtree, I'll start by giving a quick intro to the subrepo command. Let's say that you have a project repo called 'freebird' and you want to have it include 2 other external repos, 'lynyrd' and 'skynyrd'. You would do the following: git clone git@github.com/you/freebird cd freebird git subrepo clone git@github.com/you/lynyrd ext/lynyrd git subrepo clone git@github.com/you/skynyrd ext/skynyrd --branch=1975 What these commands do (at a high level) should be obvious. They "clone" (add) the repos content into the subdirectories you told them to. The details of what is happening to your repo will be discussed later, but adding new subrepos is easy. If you need to update the subrepos later: git subrepo pull ext/lynyrd git subrepo pull ext/skynyrd --branch=1976 The lynyrd repo is tracking the upstream master branch, and you've changed the skynyrd subrepo to the 1976 branch. Since these subrepos are owned by 'you', you might want to change them in the context of your freebird repo. When things are working, you can push the subrepo changes back: git subrepo push ext/lynyrd git subrepo push ext/skynyrd Looks simple right? It's supposed to be. The intent of C is to do the right things, and to not cause problems. Of course there's more to it under the hood, and that's what the rest of this article is about. =head2 Git Submodules Submodules tend to receive a lot of bad press. Here's some of it: =over =item * L =item * L =item * L =back A quick recap of some of the good and bad things about submodules: Good: =over =item * Use an external repo in a dedicated subdir of your project. =item * Pin the external repo to a specific commit. =item * The C command is a core part of the Git project. =back Bad: =over =item * Users have to know a repo has submodules. =item * Users have to get the subrepos manually. =item * Pulling a repo with submodules won't pull in the new submodule changes. =item * A submodule will break if the referenced repo goes away. =item * A submodule will break if a forced push removes the referenced commit. =item * Can't use different submodules/commits per main project branch. =item * Can't "try out" a submodule on alternate branch. =item * Main repo can be pushed upstream pointing to unpushed submod commits. =item * Command capability differs across Git versions. =item * Often need to change remote url, to push submodule changes upstream. =item * Removing or renaming a submodule requires many steps. =back Internally, submodules are a real mess. They give the strong impression of being bolted on, well after Git was designed. Some commands are aware of the existence of submodules (although usually half-heartedly), and many commands are oblivious. For instance the git-clone command has a C<--recursive> option to clone all subrepos, but it's not a default, so you still need to be aware of the need. The git-checkout command does nothing with the submodules, even if they are intended to differ across branches. Let's talk a bit about how submodules are implemented in Git. Information about them is stored in 3 different places (in the top level repo directory): =over =item * C<.gitmodules> =item * C<.git/config> =item * C<.git/modules> — The submodule repo's meta data (refs/objects) =back So some of the information lives in the repo history (.gitmodules), but other info (.git/) is only known to the local repo. In addition, the submodule introduces a new low level concept, to the commitIblob graph. Normally a git tree object points to blob (file) objects and more tree (directory) objects. Submodules have tree objects point to B objects. While this seems clever and somewhat reasonable, it also means that every other git command (which was built on the super clean Git data model) has to be aware of this new possibility (and deal with it appropriately). The point is that, while submodules are a real need, and a lot of work has gone into making them work decently, they are essentially a kludge to the Git model, and it is quite understandable why they haven't worked out as well as people would expect. NOTE: Submodules I getting better with each release of Git, but it's still an endless catch up game. =head2 Git Subtrees One day, someone decided to think different. Instead of pointing to external repos, why not just include them into the main repo (but also allow them to be pulled and pushed separately as needed)? At first this may feel like a wasteful approach. Why keep other repos physically inside your main one? But if you think about it abstractly, what's the difference? You want your users and collaborators to have all this code because your project needs it. So why worry about how it happens? In the end, the choice is yours, but I've grown very comfortable with this concept and I'll try to justify it well. I should note that the first paragraph of the C doc suggests considering this alternative. The big win here is that you can do this using the existing git model. Nothing new is added. You are just adding commits to a history. You can do it different on every branch. You can merge branches sensibly. The git-subtree command seems to have been inspired by Git's subtree merge strategy, which it uses internally, and possibly got its name from. A subtree merge allows you to take a completely separate Git history and make it be a subdirectory of your repo. Adding a subtree was the easy part. All that needed to be done after that was to figure out a way to pull upstream changes and push local ones back upstream. And that's what the C command does. So what's the problem with git-subtree then? Well unfortunately, it drops a few balls. The main problems come down to an overly complicated commandline UX, poor collaborator awareness, and a fragile and messy implementation. Good: =over =item * Use an external repo in a dedicated subdir of your project. =item * Pin the external repo to a specific commit. =item * Users get everything with a normal clone command. =item * Users don't need to know that subtrees are involved. =item * Can use different submodules/commits per main project branch. =item * Users don't need the subtree command. Only owners and collaborators. =back Bad: =over =item * The remote url and branch info is not saved (except in the history). =item * Owners and collaborators have to enter the remote for every command. =item * Collaborators aren't made aware that subtrees are involved. =item * Pulled history is not squashed by default. =item * Creates a messy historical view. (See below) =item * Bash code is complicated. =item * Only one test file. Currently is failing. =back As you can see, subtree makes quite a few things better, but after trying it for a while, the experience was more annoying than submodules. For example, consider this usage: $ git subtree add --squash --prefix=foo git@github.com:my/thing mybranch # weeks go by… $ git subtree pull --squash --prefix=foo git@github.com:my/thing mybranch # time to push local subtree changes back upstream $ git subtree push --prefix=foo git@github.com:my/thing mybranch The first thing you notice is the overly verbose syntax. It's justified in the first command, but in the other 2 commands I really don't want to have to remember what the remote and branch are that I'm using. Moreover, my collaborators have no idea that subtrees are involved, let alone where they came from. Consider the equivalent subrepo commands: $ git subrepo clone git@github.com:my/thing foo -b mybranch $ git subrepo pull foo $ git subrepo push foo Collaborators see a file called 'foo/.gitrepo', and know that the subdir is a subrepo. The file contains all the information needed by future commands applied to that subrepo. =head2 Git Subrepos Now is a good time to dive into the techinical aspects of the C command, but first let me explain how it came about. As you may have surmised by now, I am the author of git-subrepo. I'd used submodules on and off for years, and when I became aware of subtree I gave it a try, but I quickly realized its problems. I decided maybe it could be improved. I decided to write down my expected commandline usage and my ideals of what it would and would not do. Then I set off to implement it. It's been a long road, but what I ended up with was even better than what I wanted from the start. Let's review the Goods and Bads: Good: =over =item * Use an external repo in a dedicated subdir of your project. =item * Pin the external repo to a specific commit. =item * Users get everything with a normal clone command. =item * Users don't need to know that subrepos are involved. =item * Can use different submodules/commits per main project branch. =item * Meta info is kept in an obvious place. =item * Everyone knows when a subdir is a subrepo. =item * Commandline UX is minimal and intuitive. =item * Pulled history is always squashed out locally. =item * Pushed history is kept intact. =item * Creates a clean historical view. (See below) =item * Bash code is very simple and easy to follow. =item * Comprehensive test suite. =back Bad: =over =item * --Subrepo is very new.-- (no longer true) =item * --Not well tested in the wild.-- (no longer true) =back This review may seem somewhat slanted, but I honestly am not aware of any "bad" points that I'm not disclosing. That said, I am sure time will reveal bugs and shortcomings. Those can usually be fixed. Hopefully the B is correct, because that's harder to fix down the road. OK. So how does it all work? There are 3 main commands: cloneIpush. Let's start with the clone command. This is the easiest part. You give it a remote url, possibly a new subdir to put it, and possibly a remote branch to use. I say possibly, because the command can guess the subdir name (just like the git-clone command does), and the branch can be the upstream default branch. Given this we do the following steps internally: =over =item * Fetch the remote content (for a specific refspec) =item * Read the remote head tree into the index =item * Checkout the index into the new subdir =item * Create a new subrepo commit object for the subdir content =item * Add a state file called .gitrepo to the new subrepo/subdir =item * Amend the merge commit with this new file =back This process adds something like this to the top of your history: * 9b6ddc9 git subrepo clone git@github.com:you/foo.git foo/ * 37c61a5 Previous head commit of your repo The entire history has been squashed down into one commit, and placed on top of your history. This is important as it keeps your history as clean as possible. You don't need to have the subrepo history in your main project, since it is immutably available elsewhere, and you have a pointer to that place. The new foo/.gitrepo file looks like this: [subrepo] remote = git@github.com:you/foo.git branch = master commit = 14c96c6931b41257b2d42b2edc67ddc659325823 parent = 37c61a5a234f5dd6f5c2aec037509f50d3a79b8f cmdver = 0.1.0 It contains all the info needed now and later. Note that the repo url is the generally pushable form, rather than the publically readable (L form. This is the best practice. Users of your repo don't need access to this url, because the content is already in your repo. Only you and your collaborators need this url to pull/push in the future. The next command is the pull command. Normally you just give it the subrepo's subdir path (although you can change the branch with -b), and it will get the other info from the subdir/.gitrepo file. The pull command does these steps: =over =item * Fetch the upstream content =item * Check if anything needs pulling =item * Create a branch of local subrepo commits since last pull =item * Rebase this branch onto the upstream commits =item * Commit the HEAD of the rebased content =item * Update/amend the .gitrepo file =back =head3 Clean History I've talked a bit about clean history but let me show you a comparison between subrepo and subtree. Let's run this command sequence using both methods. Note the differences between I the command syntax required, and the branch history produced. Subrepo first: $ git subrepo clone git@github.com:user/abc $ git subrepo clone git@github.com:user/def xyz $ git subrepo pull abc $ git subrepo pull xyz The resulting history is: * b1f60cc subrepo pull xyz * 4fb0276 subrepo pull abc * bcef2a0 subrepo clone git@github.com:user/def xyz * bebf0db subrepo clone git@github.com:user/abc * 64eeaa6 (origin/master, origin/HEAD) O HAI FREND Compare that to B. This: $ git subtree add abc git@github.com:user/abc master $ git subtree add xyz git@github.com:user/def master $ git subtree pull abc git@github.com:user/abc master $ git subtree pull xyz git@github.com:user/def master Produces this: * 739e45a (HEAD, master) Merge commit '5f563469d886d53e19cb908b3a64e4229f88a2d1' |\ | * 5f56346 Squashed 'xyz/' changes from 08c7421..365409f * | 641f5e5 Merge commit '8d88e90ce5f653ed2e7608a71b8693a2174ea62a' |\ \ | * | 8d88e90 Squashed 'abc/' changes from 08c7421..365409f * | | 1703ed2 Merge commit '0e091b672c4bbbbf6bc4f6694c475d127ffa21eb' as 'xyz' |\ \ \ | | |/ | |/| | * | 0e091b6 Squashed 'xyz/' content from commit 08c7421 | / * | 07b77e7 Merge commit 'cd2b30a0229d931979ed4436b995875ec563faea' as 'abc' |\ \ | |/ | * cd2b30a Squashed 'abc/' content from commit 08c7421 * 64eeaa6 (origin/master, origin/HEAD) O HAI FREND This was from a minimal case. Subtree history (when viewed this way at least) gets unreasonably ugly fast. Subrepo history, by contrast, always looks as clean as shown. The final command, push, bascially just does the pull/rebase dance above described, and pushes the resulting history back. It does not squash the commits made locally, because it assumed that when you changed the local subrepo, you made messages that were intended to eventually be published back upstream. =head2 Conflict Resolution The commands described above can also be done "by hand". If something fails during a pull or push (generally in the rebasing) then the command will tell you what to do to finish up. You might choose to do everything by hand, and do your own merging strategies. This is perfectly reasonable. The C command offers a few other helper commands to help you get the job done: =over =item * C - Fetch the upstream and create a C<< subrepo/remote/ >> ref. =item * C - Create a branch of local subdir commits since the last pull, called C<< subrepo/ >>. =item * C - Commit a merged branch's HEAD back into your repo. =item * C - Show lots of useful info about the current state of the subrepos. =item * C - Remove branches, ref and remotes created by subrepo commands. =item * C - Read the complete documentation! =back =head2 Conclusion Hopefully by now, you see that submodules are a painful choice with a dubious future, and that subtree, while a solid idea has many usage issues. Give C a try. It's painless, easily revertable and just might be what the doctor ordered. =head2 Reference Links =over =item * L =item * L =back =cut git-subrepo-0.4.9/License000066400000000000000000000020751465047656200153140ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2013-2020 Ingy döt Net Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. git-subrepo-0.4.9/Makefile000066400000000000000000000053321465047656200154460ustar00rootroot00000000000000SHELL := bash # Make sure we have git: ifeq ($(shell which git),) $(error 'git' is not installed on this system) endif # Set variables: NAME := git-subrepo LIB := lib/$(NAME) DOC := doc/$(NAME).swim MAN1 := man/man1 EXT := $(LIB).d EXTS := $(shell find $(EXT) -type f) \ $(shell find $(EXT) -type l) SHARE = share # Install variables: PREFIX ?= /usr/local INSTALL_LIB ?= $(DESTDIR)$(shell git --exec-path) INSTALL_EXT ?= $(INSTALL_LIB)/$(NAME).d INSTALL_MAN1 ?= $(DESTDIR)$(PREFIX)/share/man/man1 # Docker variables: DOCKER_TAG ?= 0.0.6 DOCKER_IMAGE := ingy/bash-testing:$(DOCKER_TAG) BASH_VERSIONS ?= 5.1 5.0 4.4 4.3 4.2 4.1 4.0 DOCKER_TESTS := $(BASH_VERSIONS:%=docker-test-%) GIT_VERSIONS := 2.45 2.40 2.30 2.29 2.25 2.17 2.7 prove ?= test ?= test/ bash ?= 5.1 git ?= 2.45 # Basic targets: default: help help: @echo 'Makefile rules:' @echo '' @echo 'test Run all tests' @echo 'install Install $(NAME)' @echo 'uninstall Uninstall $(NAME)' @echo 'env Show environment variables to set' .PHONY: test test: prove $(prove) $(test) test-all: test docker-tests docker-test: $(call docker-make-test,$(bash),$(git)) docker-tests: $(DOCKER_TESTS) $(DOCKER_TESTS): $(call docker-make-test,$(@:docker-test-%=%),$(git)) # Install support: install: install -d -m 0755 $(INSTALL_LIB)/ install -C -m 0755 $(LIB) $(INSTALL_LIB)/ install -d -m 0755 $(INSTALL_EXT)/ install -C -m 0644 $(EXTS) $(INSTALL_EXT)/ install -d -m 0755 $(INSTALL_MAN1)/ install -C -m 0644 $(MAN1)/$(NAME).1 $(INSTALL_MAN1)/ # Uninstall support: uninstall: rm -f $(INSTALL_LIB)/$(NAME) rm -fr $(INSTALL_EXT) rm -f $(INSTALL_MAN1)/$(NAME).1 env: @echo "export PATH=\"$$PWD/lib:\$$PATH\"" @echo "export MANPATH=\"$$PWD/man:\$$MANPATH\"" # Doc rules: .PHONY: doc update: doc compgen force: doc: ReadMe.pod Intro.pod $(MAN1)/$(NAME).1 perl pkg/bin/generate-help-functions.pl $(DOC) > \ $(EXT)/help-functions.bash ReadMe.pod: $(DOC) force swim --to=pod --wrap --complete $< > $@ Intro.pod: doc/intro-to-subrepo.swim force swim --to=pod --wrap --complete $< > $@ $(MAN1)/%.1: doc/%.swim Makefile force swim --to=man --wrap $< > $@ compgen: force perl pkg/bin/generate-completion.pl bash $(DOC) $(LIB) > \ $(SHARE)/completion.bash perl pkg/bin/generate-completion.pl zsh $(DOC) $(LIB) > \ $(SHARE)/zsh-completion/_git-subrepo clean: rm -fr tmp test/tmp define docker-make-test docker run --rm \ -v $(PWD):/git-subrepo \ -w /git-subrepo \ $(DOCKER_IMAGE) \ /bin/bash -c ' \ set -x && \ [[ -d /bash-$(1) ]] && \ [[ -d /git-$(2) ]] && \ export PATH=/bash-$(1)/bin:/git-$(2)/bin:$$PATH && \ bash --version && \ git --version && \ make test prove=$(prove) test=$(test) \ ' endef git-subrepo-0.4.9/Meta000066400000000000000000000010471465047656200146160ustar00rootroot00000000000000=meta: 0.0.2 name: git-subrepo version: 0.4.9 abstract: Git Submodule Alternative homepage: https://github.com/ingydotnet/git-subrepo#readme license: MIT copyright: 2013-2024 author: name: Ingy döt Net email: ingy@ingy.net github: ingydotnet twitter: ingydotnet freenode: ingy homepage: http://ingy.net requires: bash: 4.0.0 git: 2.7.0 test: cmd: make test install: make install devel: git: git@github.org:ingydotnet/git-subrepo.git irc: irc.freenode.net/gitcommands bug: https://github.com/ingydotnet/git-subrepo/issues/ git-subrepo-0.4.9/ReadMe.pod000066400000000000000000000542361465047656200156560ustar00rootroot00000000000000=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.48. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 Name git-subrepo - Git Submodule Alternative =head1 Synopsis git subrepo -h # Help Overview git subrepo clone [] git subrepo init git subrepo pull git subrepo push git subrepo fetch git subrepo branch git subrepo commit git subrepo config git subrepo status [] git subrepo clean git subrepo help [ | --all] git subrepo version git subrepo upgrade =head1 Description This git command "clones" an external git repo into a subdirectory of your repo. Later on, upstream changes can be pulled in, and local changes can be pushed back. Simple. =head1 Benefits This command is an improvement from C and C; two other git commands with similar goals, but various problems. It assumes there are 3 main roles of people interacting with a repo, and attempts to serve them all well: =over =item * B - The person who authors/owns/maintains a repo. =item * B - People who are just using/installing the repo. =item * B - People who commit code to the repo and subrepos. =back The C command benefits these roles in the following ways: =over =item * Simple and intuitive commandline usage (with tab completion). =item * Users get your repo and all your subrepos just by cloning your repo. =item * Users do not need to install C, ever. =item * Collaborators do not need to install unless they want to push/pull. =item * Collaborators know when a subdir is a subrepo (it has a C<.gitrepo> file). =item * The C<.gitrepo> file never gets pushed back to the subrepo upstream. =item * Well named branches and remotes are generated for manual operations. =item * Owners do not deal with the complications of keeping submodules in sync. =item * Subrepo repositories can contain subrepos themselves. =item * Branching with subrepos JustWorks™. =item * Different branches can have different subrepos in different states, etc. =item * Moving/renaming/deleting a subrepo subdir JustWorks™. =item * You can C an existing subdirectory into a subrepo. =item * Your git history is kept squeaky clean. =item * Upstream history (clone/pull) is condensed into a single commit. =item * Pulls can use a C, C or C strategies. =item * You can see the subrepo history with C<< git log subrepo//fetch >>. =item * Commits pushed back upstream are B condensed (by default). =item * Trivial to try any subrepo operations and then reset back. =item * No configuration required. =item * Does not introduce history that messes up other git commands. =item * Fixes known rebase failures with C. =back =head1 Installation The best short answer is: git clone https://github.com/ingydotnet/git-subrepo /path/to/git-subrepo echo 'source /path/to/git-subrepo/.rc' >> ~/.bashrc The complete "Installation Instructions" can be found below. Note: git-subrepo needs a git version (> 2.7) that supports worktree:s. =head1 Commands All the B commands use names of actual Git commands and try to do operations that are similar to their Git counterparts. They also attempt to give similar output in an attempt to make the subrepo usage intuitive to experienced Git users. Please note that the commands are I exact equivalents, and do not take all the same arguments. Keep reading… =over =item C<< git subrepo clone [] [-b ] [-f] [-m ] [--file=] [-e] [--method ] >> Add a repository as a subrepo in a subdir of your repository. This is similar in feel to C. You just specify the remote repo url, and optionally a sub-directory and/or branch name. The repo will be fetched and merged into the subdir. The subrepo history is I into a single commit that contains the reference information. This information is also stored in a special file called C<< /.gitrepo >>. The presence of this file indicates that the directory is a subrepo. All subsequent commands refer to the subrepo by the name of the I. From the subdir, all the current information about the subrepo can be obtained. The C<--force> option will "reclone" (completely replace) an existing subdir. The C<--method> option will decide how the join process between branches are performed. The default option is merge. The C command accepts the C<--branch=> C<--edit>, C<--file>, C<--force> and C<--message=> options. =item C<< git subrepo init [-r ] [-b ] [--method ] >> Turn an existing subdirectory into a subrepo. If you want to expose a subdirectory of your project as a published subrepo, this command will do that. It will split out the content of a normal subdirectory into a branch and start tracking it as a subrepo. Afterwards your original repo will look exactly the same except that there will be a C<</.gitrepo >> file. If you specify the C<--remote> (and optionally the C<--branch>) option, the values will be added to the C<< /.gitrepo >> file. The C<--remote> option is the upstream URL, and the C<--branch> option is the upstream branch to push to. These values will be needed to do a C command, but they can be provided later on the C command (and saved to C<</.gitrepo >> if you also specify the C<--update> option). Note: You will need to create the empty upstream repo and push to it on your own, using C<< git subrepo push >>. The C<--method> option will decide how the join process between branches are performed. The default option is merge. The C command accepts the C<--branch=> and C<--remote=> options. =item C<< git subrepo pull |--all [-M|-R|-f] [-m ] [--file=] [-e] [-b ] [-r ] [-u] >> Update the subrepo subdir with the latest upstream changes. The C command fetches the latest content from the remote branch pointed to by the subrepo's C<.gitrepo> file, and then tries to merge the changes into the corresponding subdir. It does this by making a branch of the local commits to the subdir and then merging or rebasing (see below) it with the fetched upstream content. After the merge, the content of the new branch replaces your subdir, the C<.gitrepo> file is updated and a single 'pull' commit is added to your mainline history. The C command will attempt to do the following commands in one go: git subrepo fetch git subrepo branch git merge/rebase subrepo//fetch subrepo/ git subrepo commit # Only needed for a consequential push: git update-ref refs/subrepo//pull subrepo/ In other words, you could do all the above commands yourself, for the same effect. If any of the commands fail, subrepo will stop and tell you to finish this by hand. Generally a failure would be in the merge or rebase part, where conflicts can happen. Since Git has lots of ways to resolve conflicts to your personal tastes, the subrepo command defers to letting you do this by hand. When pulling new data, the method selected in clone/init is used. This has no effect on the final result of the pull, since it becomes a single commit. But it does affect the resulting C<< subrepo/ >> branch, which is often used for a subrepo C command. See 'push' below for more information. If you want to change the method you can use the C command for this. When you pull you can assume a fast-forward strategy (default) or you can specify a C<--rebase>, C<--merge> or C<--force> strategy. The latter is the same as a C operation, using the current remote and branch. Like the C command, C will squash all the changes (since the last pull or clone) into one commit. This keeps your mainline history nice and clean. You can easily see the subrepo's history with the C command: git log refs/subrepo//fetch The set of commands used above are described in detail below. The C command accepts the C<--all>, C<--branch=>, C<--edit>, C<--file>, C<--force>, C<--message=>, C<--remote=> and C<--update> options. =item C<< git subrepo push |--all [] [-m msg] [--file=] [-r ] [-b ] [-M|-R] [-u] [-f] [-s] [-N] >> Push a properly merged subrepo branch back upstream. This command takes the subrepo branch from a successful pull command and pushes the history back to its designated remote and branch. You can also use the C command and merge things yourself before pushing if you want to (although that is probably a rare use case). The C command requires a branch that has been properly merged/rebased with the upstream HEAD (unless the upstream HEAD is empty, which is common when doing a first C after an C). That means the upstream HEAD is one of the commits in the branch. By default the branch ref C<< refs/subrepo//pull >> will be pushed, but you can specify a (properly merged) branch to push. After that, the C command just checks that the branch contains the upstream HEAD and then pushes it upstream. The C<--force> option will do a force push. Force pushes are typically discouraged. Only use this option if you fully understand it. (The C<--force> option will NOT check for a proper merge. ANY branch will be force pushed!) The C command accepts the C<--all>, C<--branch=>, C<--dry-run>, C<--file>, C<--force>, C<--merge>, C<--message>, C<--rebase>, C<--remote=>, C<--squash> and C<--update> options. =item C<< git subrepo fetch |--force --all [-r ] [-b ] >> Fetch the remote/upstream content for a subrepo. It will create a Git reference called C<< subrepo//fetch >> that points at the same commit as C. It will also create a remote called C<< subrepo/ >>. These are temporary and you can easily remove them with the subrepo C command. The C command accepts the C<--force>, C<--all>, C<--branch=> and C<--remote=> options. =item C<< git subrepo branch |--all [-f] [-F] >> Create a branch with local subrepo commits. Scan the history of the mainline for all the commits that affect the C and create a new branch from them called C<< subrepo/ >>. This is useful for doing C and C commands by hand. Use the C<--force> option to write over an existing C<< subrepo/ >> branch. The C command accepts the C<--all>, C<--fetch> and C<--force> options. =item C<< git subrepo commit [] [-m ] [--file=] [-e] [-f] [-F] >> Add subrepo branch to current history as a single commit. This command is generally used after a hand-merge. You have done a C and merged (rebased) it with the upstream. This command takes the HEAD of that branch, puts its content into the subrepo subdir and adds a new commit for it to the top of your mainline history. This command requires that the upstream HEAD be in the C<< subrepo/ >> branch history. That way the same branch can push upstream. Use the C<--force> option to commit anyway. The C command accepts the C<--edit>, C<--fetch>, C<--file>, C<--force> and C<--message=> options. =item C<< git subrepo status [|--all|--ALL] [-F] [-q|-v] >> Get the status of a subrepo. Uses the C<--all> option by default. If the C<--quiet> flag is used, just print the subrepo names, one per line. The C<--verbose> option will show all the recent local and upstream commits. Use C<--ALL> to show the subrepos of the subrepos (ie the "subsubrepos"), if any. The C command accepts the C<--all>, C<--ALL>, C<--fetch>, C<--quiet> and C<--verbose> options. =item C<< git subrepo clean |--all|--ALL [-f] >> Remove artifacts created by C and C commands. The C and C operations (and other commands that call them) create temporary things like refs, branches and remotes. This command removes all those things. Use C<--force> to remove refs. Refs are not removed by default because they are sometimes needed between commands. Use C<--all> to clean up after all the current subrepos. Sometimes you might change to a branch where a subrepo doesn't exist, and then C<--all> won't find it. Use C<--ALL> to remove any artifacts that were ever created by subrepo. To remove ALL subrepo artifacts: git subrepo clean --ALL --force The C command accepts the C<--all>, C<--ALL>, and C<--force> options. =item C<< git subrepo config