[petsc-dev] git worktree
Jed Brown
jed at jedbrown.org
Tue May 18 18:17:03 CDT 2021
I don't follow the advantage over lightweight clones, such as:
$ git clone --branch=release --reference petsc gitlab:petsc/petsc petsc-release
Cloning into 'petsc-release'...
remote: Enumerating objects: 261, done.
remote: Counting objects: 100% (261/261), done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 474 (delta 213), reused 239 (delta 207), pack-reused 213
Receiving objects: 100% (474/474), 430.41 KiB | 1.96 MiB/s, done.
Resolving deltas: 100% (296/296), completed with 110 local objects.
Updating files: 100% (9721/9721), done.
$ cd petsc-release/
release= ~/petsc-release$ du -hs .git
2.3M .git
Scott Kruger <kruger at txcorp.com> writes:
> Relatively recently, I learned about the git worktree feature and
> attached my write-up of how I use it in petsc. I have no idea whether
> the response will be:
>
> This has been around since 2015 at least, and you're just now
> finding out about it? LOL!
>
> or:
>
> I can't believe I never heard about it either!
>
>
> Since Patrick recently talked about shallow clones with git on slack, I
> suspect it's the latter (and I didn't hear about this feature from petsc
> dev's which is where I typically gain all my git knowledge). Basically,
> if you have more than one clone of petsc on your drive, you'll be
> interested in the worktree feature.
>
> The reason why the write-up is a bit long boils down the fact that we
> have the `/` in our branch names. It makes things a bit more
> complicated compared to my other projects (but is nice for the directory
> structure). I have not scripted away the complexity either -- I haven't
> reached that level of annoyance.
>
> The reason why I just don't have the rst file as an MR, is because the
> way I have it point to an existing branch seems cumbersome. Perhaps a
> git guru knows an easier way with some type of detached state or faster
> way of getting the HEAD to point to the right sha in one go. I'd be
> very interested if someone knows a better method.
>
> Scott
>
>
> --
> Scott Kruger
> Tech-X Corporation kruger at txcorp.com
> 5621 Arapahoe Ave, Suite A Phone: (720) 466-3196
> Boulder, CO 80303 Fax: (303) 448-7756
>
>
> Working on multiple branches simultaneously
> ===========================================
>
> Our goal is to have a parallel structure of directories each with a different
> branch.
>
> Let's start off with the basic structure::
>
> - ptroot
> |- petsc (main)
>
>
> The petsc directory is the directory that comes from `git clone` and we
> have main as a general branch.
>
> The simplest example is to do a quick bugfix in a separate worktree::
>
> git worktree add ../petsc-bugfix
>
> The output of this is::
>
> Preparing worktree (new branch 'petsc-bugfix')
> Updating files: 100% (9829/9829), done.
> HEAD is now at ...
>
> The directory is now this::
>
> - ptroot
> |- petsc (main)
> |
> |- petsc-bugfix (petsc-bugfix)
>
> This is like a separate clone, but is more lightweight because it does not copy
> over the `.git` directory (it has a `.git` file instead) and has advantages
> because typing `git branch` shows information on all of the worktree's::
>
> * main
> + petsc-bugfix
>
> where the `*` denotes the branch of the directory we are in and `+` denotes
> other worktree branches (this appears to be a feature in newer versions of git).
>
>
> The naming convention of a git branch in petsc is `developer/branch-name`; e.g.,
> `scott/test-fix-reporting`. The slash will introduce some wrinkles into the
> normal worktree usage. Let's try this::
>
> git worktree add ../scott/test-fix-reporting
>
> We now have::
>
> - ptroot
> |- petsc (main)
> |
> |- petsc-bugfix (petsc-bugfix)
> |
> |- scott
> |
> |- test-fix-reporting (test-fix-reporting)
>
>
> which isn't *exactly* what we wanted. Instead, we use the `-b` flag to use the
> right branch name::
>
> git worktree add -b 'scott/test-fix-reporting' ../scott/test-fix-reporting
> cd ../scott/test-fix-reporting
> git branch --set-upstream-to=origin/scott/test-fix-reporting scott/test-fix-reporting
>
> The last 2 steps were to avoid using the `--set-upstream` to the first `git
> push`. Those two steps are not strictly necessary.
>
> (Aside: `git worktree add` can take a 3rd argument to give the branch name and
> many tutorials use that; however that doesn't work with `/` in the name. The
> documentation itself says that the argument is `commit-ish`. The `-b` argument
> is needed for the PETSc naming convention.)
>
> We now have::
>
> - ptroot
> |- petsc (main)
> |
> |- petsc-bugfix (petsc-bugfix)
> |
> |- scott
> |
> |- test-fix-reporting (scott/test-fix-reporting)
>
> which is what we wanted as `git branch` shows (again, assuming a newer version
> of git)::
>
> > git branch
> + main
> + petsc-bugfix
> + scott/test-fix-reporting
>
> This provides a nicely organized structure.
>
> Tracking an existing remote branch
> ===================================
>
> The above shows a worktree based on performing the equivalent of
> a `git checkout -b` to start with a new branch. Here, we show how to follow
> an existing remote branch.
> For reasons given by the Aside above, our naming scheme makes this a bit more
> complicated. Here is what I have working::
>
> # Get version that matches remote branch
> git checkout barry/feature-pintogpu
>
> # Need to create worktree with different name at the remote branch to avoid conflicts
> git checkout -b temp
>
> # About to create a branch with the same name so delete
> git branch -D barry/feature-pintogpu
>
> # Local branch name matches worktree
> git worktree add -b'barry/feature-pintogpu' ../barry/feature-pintogpu
>
> # Cleanup
> git checkout main; git branch -D temp
>
> # Point the worktree to match the remote branch and pull for testing
> cd ../barry/feature-pintogpu/
> git branch --set-upstream-to=origin/barry/feature-pintogpu barry/feature-pintogpu
> git pull
>
>
>
> Cleaning up
> ============
>
> Using worktrees is much lighter weight than separate clones and it's easy to end
> up with additional directories that you want to clean up. The easiest is to do
> the inverse of the add command::
>
> git worktree remove ../scott/test-fix-reporting
>
>
> Other features
> ===============
>
> The above commands and workflow handle most of what you need about worktrees,
> but running `git worktree --help` shows additional commands. Most of them are
> obvious: you can move a working directory, you can clean up (`prune`) some of the
> worktree information if you delete a directory without using the `remove` command,
> etc.
>
>
>
> Comments on other workflows
> ================================
>
> It is useful to have a good organization so that one can distinguish between the
> original clone (which has a `.git` subdirectory) and the worktrees (which has a
> `.git` file which you can examine). Other tutorials have the worktrees as
> subdirectories of the original clone. This seems confusing as it is not as
> obvious in how git operations (such as `git grep`) will work.
>
> Another common workflow is to have a single directory that has rolling fixes on
> a given topic. This workflow is valid and totally works as one can change
> directories in a worktree. The main problem however is this:
>
> *no branch may be checked at the same time*
>
> This means that if I have a directory of `../scott/test` that always has my work
> on test harness development, the main problem I will have is getting that
> directory up to `main`. The fix is to have a branch that can be used to track
> `main`: `test-main` created in my `petsc` directory. The workflow would then
> be::
>
> cd ../scott/test
> git checkout test-main
> git rebase main
> git checkout -b scott/test-very-specific-fix
>
> Different workflows are possible of course, but this gives a flavor of the basic
> steps needed to create your own and fits within the common petsc labelling
> scheme.
More information about the petsc-dev
mailing list