- Git worktree vs submodule
- Git submodule
- Git subtree vs submodule
- Git work-tree
- Git worktree remove
- Git config worktree
- Git submodule update
- Git worktree move
- Git subtree tutorial
Git worktree vs submodule
Clean coder. Rock climber. Recently, I was in a situation in which I really needed two separate copies of my Git repository. I was about to make a full clone of the repository, but I decided to see if Git had a better solution. And in fact, Git introduced the worktree feature not too long ago as of version 2. All you need to do is set up a new worktree like this:. This will set up the directory. You can create this directory anywhere on the same filesystem, but it should be somewhere outside of your main repository directory! You can then proceed to use the worktree directory as usual, checking out branches, pushing upstream, etc. In a large project with very good test coverage, some test suites can take a long time to run—far beyond a convenient amount of time to sit and wait for them to finish. Many IDEs allow opening multiple projects at once, but each must be in its own directory. You could git clone two entirely separate repositories, but worktrees are better:. I frequently keep an extra worktree around just for running tests. I get around this by creating local temporary branches, like so:. I use the TEMP prefix to emphasize that the branch is temporary my shell prompt includes the name of the current branch, so this practically yells it at me. What you really need is to see both versions simultaneously so you can compare things side-by-side or even run both versions at the same time. You can easily check out a previously tagged version or any arbitrary commit in a worktree. Switching branches may also have undesired side effects depending on your project for example, causing an IDE to re-index. Everybody has probably had the experience of a build failure because a co-worker forgot to include some files with a commit. It could be that they forgot to add the files to Git, or perhaps some. If the build works for them but not for you, then you may be missing some files. One way to find out is to test it against a working copy that you know to be clean. Since worktrees give you a clean checkout, they can be used to verify that all of the files that need to be included have been added to Git.
Git submoduleDuring development of DbLocalizationProvider I had single repository in GitHub containing more that one package as result of the build. Initially there was just a EPiServer package to add support for database driven localization resources. Later realized that there is actually not so much to do to add support for Asp. Net Mvc. NET Framework applications and later also for. NET Core applications. As you can see there might be some issue with having multiple purpose packages with different life-cycles and versions located in single Git repository. So decided to split whole code-base into git submodules and setup separate repositories for each of the sub-systems. This is a blog post about the stuff I had to do. It's important to understand where each module ends and where next begins as you be referencing each other through sort of NuGet package references. Decision has to be made around type locations - where each type should go and which project will be used where. Actually for development purposes using ordinary project reference is much more preferred way to work with. This gives nicer debugger experience for developer without any hustle to enable symbols and be able to "step into" the package source code. Now when you have decided module boundaries it's time to create repositories for each of the module. After we have main module repository available, we can create new one for Asp. Net Mvc aspnet packages. Now tricky part is that I would like to include source from main repository as part of the solution - like normal projects. Then I would be able to debug it through, change and adjust on-demand if needed, etc. We need to " include " projects from main repository into aspnet repository. This is achievable by "linking" main repository content into aspnet. Keep in mind that linking is possible by pointing to some directory under which linked repository content will be "cloned". Information about just added submodule is written in. This is very important to remember that submodule linking sets included submodule into detached HEAD state. Meaning that when working with submodules - this rare git case becomes norm. As you would like to refer to particular commit and not tracking branch, which is essentially a moving target. You want to "lock down" yourself to specific version of the submodule. This applies only to. Once you have linked main under aspnet - you need to make couple of changes for the IDE to understand new structure. Adding reference to NuGet package in Asp. Net Mvc repository Visual Studio will create following reference hint path:. Which looks quite good when working in Asp. Net Mvc repository. However, this will become problem when we will link aspnet repository one level up - in epi.
Git work-treeThis is a common topic while managing Git repositories. Sometimes, you need to have one or many repositories withing another repository. The laziest way to do it is having a monorepo. A Git monorepo is when a team develops multiple projects, related or not, in a single Git repo, in order to make it easy to share code between different projects. As example, if you have a library that you want to use in different projects, you just put it in its own folder and reference in your projects:. This is very easy to do. To do so, Git have two buildin features to make this work, Git submodules and Git subtrees. We can think of submodules as a kind of link that points to another repository. As example, imagine we are starting a repo for a web application. This repo will contain both server-side and client-side code. Now, imagine we will add Pikaday as a submodule, since we will need it in our web app. Doing that is as simple as doing:. It contains what submodules we have and its clone path. Internally, Git stores the submodule as a simple text file, with the exact commit ref it points to:. This means that the Pikaday source was not commited to the repository when we did the commit. Remember, a Git submodule is just a link to a specific ref in another repository. In order to have that, they will have to run:. There are many gotchas you have to be aware when dealing with submodules. One of them is that Git often keep your submodules checked in detached heads. Imagine we want to make a change in the Pikaday repo. First, we need to make sure we are checked in a branch often master :. Another gotcha: even after making changes to Pikaday, we have to manually update the ref in the outer repo:. These and other problems make many people prefer subtrees over submodules, which we will see next.
Git config worktree
In this post I explain why. Every organisation has code that is shared between projects, and submodules and subtrees prevent us from duplicating code across those projects, avoiding the many problems that arise if we have multiple versions of the same code. The simplest way to think of subtrees and submodules is that a subtree is a copy of a repository that is pulled into a parent repository while a submodule is a pointer to a specific commit in another repository. It also means that subtrees are much easier for other people to come and pull, as they are just part of the parent repository. Both the advantage and disadvantage of submodules is that they can and should be treated as a repository of their own. They will need to be committed to separately, and can be branched separately. You may already be able to see some of the issues that can occur if you ignore the fact that the submodule needs to be kept up to date:. Any changes from the last committed submodule commit will be listing as modified, and can be included in the next commit to the parent repository. The only difference between making changes to code within a submodule directory and a regular directory is that we must commit and push to the submodule repository before then moving up a directory and committing the pointer to the new submodule commit and pushing that to the remote of the parent repository. When the contents of a submodule folder have been modified they appear as a single line if we run git status in the parent repository:. This output from git status can be confusing, because it looks like only a single file has changed, when in fact there could be massive changes within the submodule directory. If I move up a directory, I will then be back in the parent repository, and I will see that the submodule has a new commit:. So I need to make sure that after a submodule commit I also push:. That may seem quite convoluted, but we are dealing with two separate repositories, so there is always going to be twice as much work. The order in which you commit and push changes when working with submodules is so important that I consider it the golden rule of modifying submodules…. Always commit and push the submodule changes first, before then committing the submodule change in the parent repository. Without following this rule you can get into a confusing state in which the parent repository is pointing to a submodule commit that only exists on your local machine. Issues with submodules tend to arise due to the poor tooling. This stale submodule can cause the entire project to get into a mess. If you define an alias which runs git submodule update after every single git pull then you will be safe, but a newbie is unlikely to do this. The first is the squashing down of the entire history of the remote repository that we are cloning:. And as with submodules, this is both an advantage and a disadvantage. The command will also create a similar set of commits to the earlier add. Things get really tricky when we need to push commits back to the original repository. This is understandable because our repository has no knowledge of the original repository, and has to figure out how to prepare the changes so that they can be applied to the remote before it can push. In my experience how long this takes to run depends on the amount of history in the parent repository, your OS, and your machine. After so many issues with submodules I had high hopes for subtrees, but was quite disappointed. For a start there is very little documentation. In my opinion subtrees are not a direct replacement for submodules. The way I believe you should split your shared code between subtrees and submodules is this:. View all posts by Martin Owen. That is, a clone of a module with a subtree gets the subtree with no knowledge or further action needed but with a submodule one has to either use —recursive on the clone command or issue a submodule init and update after cloning the parent. I thought subtree was a better choice, after took two days used it for one of our big project, I encountered exactly same problem you mentioned. I took advice from the Mercurial camp on subrepos. Then you get the benefit of getting everything in mostly one go yet with less risk of losing changes. You can also control who has write access to the submodules repo so as to avoid collisions. This is by far the best information I could find on submodules vs. Many thanks for taking the effort to document your experience.
Git submodule updateApr Posted by Amber. It is not uncommon at all when working on any kind of larger-scale project with Git to find yourself wanting to share code between multiple different repositories — whether it be some core system among multiple different products built on top of that system, or perhaps a shared utility library between projects. This means that if someone else updates the recorded version of a submodule and you pull their latest changes in the parent repository, your submodule repository will still be pointing to the old version of the submodule. When you invoke git submodule update it looks in the parent repository for a SHA for each submodule, goes into those submodules, and checks out the corresponding SHAs. If you then make changes in the submodule and commit then, Git will happily create the commit… and leave you still with a detached HEAD. See where this is going yet? Say you merge in some more changes which happen to include another submodule update. Submodules acting as almost completely independent repositories has another catch, too — you have to push changes from both the submodule and the parent repository to share with others. Push changes from the submodule and not the parent repository? No one knows to use your new submodule changes. Push changes from the parent repository and not the submodule? So if submodules are such a pain, what are the alternatives? Which one is best for you depends on your priorities. Repo is a tool created by Google to manage the rather large Android project, which is spread across multiple different Git project repositories. It essentially works by providing a way to check out multiple projects Git repositories in parallel based on a manifest file which basically serves the purpose that a parent repository does for Git submodules — tracking which submodule commits go together. It also provides a way to submit an atomic changeset that includes changes to multiple different projects. Gitslave is a wrapper around Git that multiplexes git commits into multiple repositories. If you commit, all of your repositories create a commit, and so on. Of course, this can get rather hectic if you have a large number of projects and start running into things like merge conflicts in 5 different repositories. Posted on April 28,in Software Development and tagged git. Bookmark the permalink. What you should be doing is checking out to a specific TAG in your submodule. This will alleviate Submodules are for things such as commonly reused libraries, not for some afternoon hack attack someone threw up all over the repository. The real meat of your comment though seems to be your specification regarding separate versioned packages. I actually agree with you — that is the use case that submodules actually work for. We used submodules for a while in our team.
Git worktree move
A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With git worktree add a new working tree is associated with the repository. This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "git clone". When you are done with a linked working tree, remove it with git worktree remove. If a working tree is deleted without using git worktree removethen its associated administrative files, which reside in the repository see "DETAILS" belowwill eventually be removed automatically see gc. If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from being pruned by issuing the git worktree lock command, optionally specifying --reason to explain why the working tree is locked. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. If the branch exists in multiple remotes and one of them is named by the checkout. Set it to e. See also checkout. List details of each worktree. The main worktree is listed first, followed by each of the linked worktrees. The output details include if the worktree is bare, the revision currently checked out, and the branch currently checked out or detached HEAD if none. If a working tree is on a portable device or network share which is not always mounted, lock it to prevent its administrative files from being pruned automatically. This also prevents it from being moved or deleted. Optionally, specify a reason for the lock with --reason. Move a working tree to a new location. Note that the main working tree or linked working trees containing submodules cannot be moved. Remove a working tree. Only clean working trees no untracked files and no modification in tracked files can be removed. Unclean working trees or ones with submodules can be removed with --force. The main working tree cannot be removed. This option overrides these safeguards. To add a missing but locked working tree path, specify --force twice. To remove a locked working tree, specify --force twice. By default, -b refuses to create a new branch if it already exists. With adddetach HEAD in the new working tree. See "Sparse checkout" in git-read-tree. This can also be set up as the default behaviour by using the worktree. See "--track" in git-branch for details. Keep the working tree locked after creation. This is the equivalent of git worktree lock after git worktree addbut without race condition. With listoutput in an easy-to-parse format for scripts. This format will remain stable across Git versions and regardless of user configuration.