<a id="how-git-workshops"></a>

# How to use workshops with Git

<!-- @tests in tests/docs-how-to/git/task.yaml -->
<!-- @artefact workshop (container) -->

Workshops are designed to be used in common development ecosystems,
which makes their encounter with Git almost inevitable.
Let’s look at how you can integrate workshops into your repo.

## Initialization

To start, place the workshop definition
in your repository:

```console
$ git init original
$ cd original/
```

```yaml
name: dev
base: ubuntu@22.04
sdks:
  - name: go
    channel: 1.26
```

Next,
launch the workshop
and start working on your code:

<!-- @artefact workshop launch -->
```console
$ workshop launch
```

```go
package main

import "fmt"

func main() {
    fmt.Println("hello, Workshop")
}
```

Mind that any activity
that relies on the workshop’s contents
should now occur inside the workshop:

<!-- @artefact workshop exec -->
```console
$ git add . && git commit -m "initial commit"
$ workshop exec dev go build -x main.go
```

<!-- @artefact project -->

However, the resulting artifacts are exposed in the project directory:

```console
$ ./main

  hello, Workshop
```

They stay there even if you remove the workshop:

<!-- @artefact workshop remove -->
```console
$ workshop remove
$ ./main

  hello, Workshop
```

From here, you can do whatever you like with your repo,
because **Workshop** handles
[moving projects around](https://ubuntu.com/workshop/docs//how-to/customize-workshops/move-projects.md#how-move-projects) quite well.

Don’t forget to add the `.workshop.lock` file to your `.gitignore` file:

```console
$ echo ".workshop.lock" >> .gitignore
```

In contrast, the definition and the `.workshop/` directory
are *meant* to be stored in a repository;
if your `.gitignore` file uses rules
such as “ignore everything except these files and directories,”
add them to the list of explicitly tracked items.

With your dependencies accounted for,
restoring your build system after cloning the repo elsewhere
is as simple as relaunching the workshop from a new
*project directory*.

But what if you need to maintain multiple branches
that require different versions of the same workshop?
A common solution is to clone the repo several times
to manually synchronize the copies when needed,
but this approach is prone to errors and overhead.
Let’s build something better and…

#### NOTE
If you did remove the workshop at this step of the guide,
relaunch it before proceeding further:

```console
$ workshop launch
```

## Use worktrees

Let’s add a Git feature that works well with workshops,
namely [`git worktree`](https://git-scm.com/docs/git-worktree).

One of **Workshop**’s goals is
to simplify toggling external dependencies
such as frameworks or OS versions.
Say you want to investigate a problem that occurs on an older OS version,
so you create a new worktree just for that:

```console
$ git worktree add ../hotfix
$ cd ../hotfix/
```

<!-- @artefact workshop base image -->

Instead of bothering with virtual machines,
update the definition
to change the base image:

```yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: go
    channel: 1.26
```

Next, launch the redefined workshop to work on the problem:

```console
$ workshop launch
$ # Hacking away until the problem is solved
$ git commit -m "solve problem with hotfix"
$ cd ../original/
$ git merge hotfix
```

As with regular directories,
**Workshop** works well with
[`git worktree move`](https://git-scm.com/docs/git-worktree#_commands):

<!-- @artefact workshop list -->
```console
$ git worktree move ../hotfix/ ../resolved/
$ workshop list --global

PROJECT     WORKSHOP  STATUS  NOTES
~/original  dev       Ready   -
~/resolved  dev       Ready   -
```

Similarly,
when it comes to clean-up,
remove all workshops
before running `git worktree remove`:

```console
$ workshop remove --project ../resolved/
$ git worktree remove ../resolved/
```

So using **git worktree** reduces the effort on sync, stash, and pull,
while **Workshop** allows you to hot-swap an entire OS
or another complex dependency
by going from one directory to another.

## See also

Explanation:

- [Base image](https://ubuntu.com/workshop/docs//explanation/workshops/concepts.md#exp-base)
- [Multi-workshop patterns](https://ubuntu.com/workshop/docs//explanation/workshops/multi-workshop-patterns.md#exp-multi-workshop-patterns)
- [Projects](https://ubuntu.com/workshop/docs//explanation/workshops/projects.md#exp-projects)
- [Workshop definition](https://ubuntu.com/workshop/docs//explanation/workshops/concepts.md#exp-workshop-definition)

How-to guides:

- [How to move projects around](https://ubuntu.com/workshop/docs//how-to/customize-workshops/move-projects.md#how-move-projects)
- [How to use workshops with AI agents](https://ubuntu.com/workshop/docs//how-to/develop-with-workshops/use-workshops-with-ai-agents.md#how-use-workshops-with-ai-agents)

Reference:

- [workshop launch](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-launch)
- [workshop remove](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-remove)
