diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Revision history for nix-thunk
 
+## 0.7.2.1
+* Loosen version bounds
+* Fix issue where thunk branches aren't updated when the user specifies --branch on nix-thunk update
+* Swap default.nix and lib.nix
+
+## 0.7.2.0
+* Support retrieving revs that aren't on the default branch when a branch isn't specified.  To use this functionality, update your thunks.
+
 ## 0.7.1.0
 * Allow specifying `--rev` when doing `update` to update to a specific revision.
 
@@ -11,7 +19,7 @@
 
 * Caching now works
 * [#42](https://github.com/obsidiansystems/nix-thunk/pull/42) Thunk read errors are now presented in a more informative manner.
-* [#43](https://github.com/obsidiansystems/nix-thunk/pull/43) `nix-thunk` will now ensure that any `git` processes invoked during its execution have a clean configuration. 
+* [#43](https://github.com/obsidiansystems/nix-thunk/pull/43) `nix-thunk` will now ensure that any `git` processes invoked during its execution have a clean configuration.
   This prevents `nix-thunk` crashing when e.g. the user's configuration `git` is valid only in a version newer than what `nix-thunk` links against, and works towards making thunks more reproducible by ensuring that thunk URIs are resolvable independently of the user's environment.
 
 ## 0.6.1.0
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@
 
 nix-thunk is a lightweight Nix dependency manager, focused on making it easy to contribute improvements back to libraries you depend on.
 
-nix-thunk does this by creating and managing "thunks" - directories that stand in for full git repositories.  Like git submodules, they pin a specific commit of the target repository, but unlike git submodules, you don't have to clone them to use them.  nix-thunk makes them "transparent" to Nix scripts, so any script that calls `import path/to/some/thunk` will work the same on the thunk as it does on the original repository.
+nix-thunk does this by creating and managing "thunks" - directories that stand in for full git repositories.
+Like git submodules, they pin a specific commit of the target repository, but unlike git submodules, you don't have to clone them to use them.
+nix-thunk makes them "transparent" to Nix scripts, so any script that calls `import path/to/some/thunk` will work the same on the thunk as it does on the original repository.
 
 * [Installation](#installation)
 * [Command Usage](#command-usage)
@@ -21,7 +23,8 @@
 nix-env -f https://github.com/obsidiansystems/nix-thunk/archive/master.tar.gz -iA command
 ```
 
-**WARNING**: It is _not_ possible to compile `nix-thunk` without Nix. To ensure that packed thunks are buildable even in environments where diamond paths are unavailable (specifically `<nixpkgs>`), `nix-thunk` _must_ be built with knowledge of a known-good nixpkgs, _and_ for `nix-thunk` to be able to manipulate these thunks, it must _always_ be the same version of nixpkgs.
+**WARNING**: It is _not_ possible to compile `nix-thunk` without Nix.
+To ensure that packed thunks are buildable even in environments where diamond paths are unavailable (specifically `<nixpkgs>`), `nix-thunk` _must_ be built with knowledge of a known-good nixpkgs, _and_ for `nix-thunk` to be able to manipulate these thunks, it must _always_ be the same version of nixpkgs.
 
 ## Command Usage
 
@@ -39,7 +42,9 @@
 
 ### Work on a dependency
 
-If you discover a bug fix or improvement that your dependency needs, you can use `nix-thunk unpack path/to/your/dependency` to turn the thunk back into a full checkout of the repository.  Your Nix scripts should continue working, and you can modify the dependency's source code, push it to a branch or a fork, send a pull request, and then use `nix-thunk pack path/to/your/dependency` to pack it back up into a thunk.  When the dependency accepts your pull request, you can easily update the thunk.
+If you discover a bug fix or improvement that your dependency needs, you can use `nix-thunk unpack path/to/your/dependency` to turn the thunk back into a full checkout of the repository.
+Your Nix scripts should continue working, and you can modify the dependency's source code, push it to a branch or a fork, send a pull request, and then use `nix-thunk pack path/to/your/dependency` to pack it back up into a thunk.
+When the dependency accepts your pull request, you can easily update the thunk.
 
 ```bash
 nix-thunk unpack some-dep
@@ -57,7 +62,10 @@
 
 ## Nix Usage
 
-The [`default.nix`](default.nix) file in this repository also defines the nix function, `thunkSource`. This can be used in your nix files to access the contents of thunks. In the following example, a thunk is used in place of the source location argument to `callCabal2nix`. `thunkSource` works whether the thunk is packed or unpacked, making it convenient to run nix commands with modified thunks.
+The [`default.nix`](default.nix) file in this repository defines the nix function, `thunkSource`.
+This can be used in your nix files to access the contents of thunks.
+In the following example, a thunk is used in place of the source location argument to `callCabal2nix`.
+`thunkSource` works whether the thunk is packed or unpacked, making it convenient to run nix commands with modified thunks.
 
 ```nix
   haskellPackages = pkgs.haskell.packages.ghc865.override {
@@ -75,7 +83,8 @@
 { which = self.callCabal2nix "which" sources.which {}; }
 ```
 
-You can also access subfolders of a thunk. For example:
+You can also access subfolders of a thunk.
+For example:
 
 ```nix
 {
@@ -90,7 +99,10 @@
 ```
 
 ## Contributing
-Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. See the [contribution guide](CONTRIBUTING.md) for more details.
+
+Pull requests are welcome.
+For major changes, please open an issue first to discuss what you would like to change.
+See the [contribution guide](CONTRIBUTING.md) for more details.
 
 ## License
 [BSD3](./LICENSE)
diff --git a/nix-thunk.cabal b/nix-thunk.cabal
--- a/nix-thunk.cabal
+++ b/nix-thunk.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               nix-thunk
-version:            0.7.2.0
+version:            0.7.2.1
 license:            BSD3
 license-file:       LICENSE
 copyright:          Obsidian Systems LLC 2020-2022
@@ -19,7 +19,7 @@
   CHANGELOG.md
   README.md
 
-tested-with: GHC ==8.6.5 || ==8.8.4
+tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.1 || ==9.2.5 || ==9.4.5 || ==9.6.1 || ==9.8.2 || ==9.10.1
 
 library
   exposed-modules:
@@ -33,33 +33,33 @@
   build-depends:
       aeson                 >=1.4.4.0  && <2.3
     , aeson-pretty          >=0.8.7    && <0.9
-    , base                  >=4.12.0.0 && <4.19
-    , bytestring            >=0.10.8.2 && <0.12
+    , base                  >=4.12.0.0 && <4.21
+    , bytestring            >=0.10.8.2 && <0.13
     , cli-extras            >=0.2.1.0  && <0.3
     , cli-git               >=0.2.0.0  && <0.3
     , cli-nix               >=0.2.0.0  && <0.3
-    , containers            >=0.6.0.1  && <0.7
+    , containers            >=0.6.0.1  && <0.8
     , cryptonite            >=0.25     && <0.31
-    , data-default          >=0.7.1.1  && <0.8
+    , data-default          >=0.7.1.1  && <0.9
     , directory             >=1.3.3.0  && <1.4
     , either                >=5.0.1.1  && <5.1
     , exceptions            >=0.10.3   && <0.11
-    , extra                 >=1.6.18   && <1.8
-    , filepath              >=1.4.2.1  && <1.5
+    , extra                 >=1.6.18   && <1.9
+    , filepath              >=1.4.2.1  && <1.6
     , github                >=0.25     && <0.30
     , here                  >=1.2.13   && <1.3
     , lens                  >=4.17.1   && <5.4
     , logging-effect        >=1.3.4    && <1.5
-    , megaparsec            >=7.0.5    && <9.7
+    , megaparsec            >=7.0.5    && <9.8
     , memory                >=0.14     && <0.19
     , modern-uri            >=0.3.1.0  && <0.4
     , monad-logger          >=0.3.30   && <0.4
     , mtl                   >=2.2.2    && <2.4
-    , optparse-applicative  >=0.14.3.0 && <0.17
+    , optparse-applicative  >=0.14.3.0 && <0.19
     , temporary             >=1.3      && <1.4
-    , text                  >=1.2.3.1  && <1.3
-    , time                  >=1.8.0.2  && <1.12
-    , unix                  >=2.7.2.2  && <2.8
+    , text                  >=1.2.3.1  && <2.2
+    , time                  >=1.8.0.2  && <1.15
+    , unix                  >=2.7.2.2  && <2.9
     , which                 >=0.2      && <0.3
     , yaml                  >=0.11.1.2 && <0.12
 
@@ -67,11 +67,11 @@
   main-is:          src-bin/nix-thunk.hs
   default-language: Haskell2010
   build-depends:
-      base                  >=4.12.0.0 && <4.19
-    , cli-extras            >=0.2.1.0  && <0.3
+      base
+    , cli-extras
     , nix-thunk
-    , optparse-applicative  >=0.14.3.0 && <0.17
-    , text                  >=1.2.3.1  && <1.3
+    , optparse-applicative
+    , text
 
 source-repository head
   type:     git
diff --git a/src-bin/nix-thunk.hs b/src-bin/nix-thunk.hs
--- a/src-bin/nix-thunk.hs
+++ b/src-bin/nix-thunk.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE PackageImports #-}
 import Nix.Thunk
 import Nix.Thunk.Command
 import Options.Applicative
diff --git a/src/Nix/Thunk.hs b/src/Nix/Thunk.hs
--- a/src/Nix/Thunk.hs
+++ b/src/Nix/Thunk.hs
@@ -1,17 +1,3 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE MultiWayIf #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PatternGuards #-}
-{-# LANGUAGE QuasiQuotes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE TypeApplications #-}
 module Nix.Thunk
   ( ThunkSource (..)
   , GitHubSource (..)
@@ -27,6 +13,8 @@
   , packThunk
   , createThunk
   , createThunk'
+  , createWorktree
+  , CreateWorktreeConfig (..)
   , ThunkPackConfig (..)
   , ThunkConfig (..)
   , updateThunkToLatest
diff --git a/src/Nix/Thunk/Command.hs b/src/Nix/Thunk/Command.hs
--- a/src/Nix/Thunk/Command.hs
+++ b/src/Nix/Thunk/Command.hs
@@ -45,24 +45,37 @@
     source = (ThunkCreateSource_Absolute <$> maybeReader (parseGitUri . T.pack))
          <|> (ThunkCreateSource_Relative <$> str)
 
+createWorktreeConfig :: Parser CreateWorktreeConfig
+createWorktreeConfig = CreateWorktreeConfig
+  <$> optional (strOption (short 'b' <> long "branch" <> metavar "BRANCH" <> help "create a new branch"))
+  <*> switch (long "detach" <> short 'd' <> help "detach HEAD at the commit specified in thunk")
+
 data ThunkCommand
   = ThunkCommand_Update ThunkUpdateConfig (NonEmpty FilePath)
   | ThunkCommand_Unpack (NonEmpty FilePath)
+  | ThunkCommand_Worktree CreateWorktreeConfig (FilePath, FilePath)
   | ThunkCommand_Pack ThunkPackConfig (NonEmpty FilePath)
   | ThunkCommand_Create ThunkCreateConfig
   deriving Show
 
 thunkDirList :: Parser (NonEmpty FilePath)
 thunkDirList = (:|)
-  <$> thunkDirArg (metavar "THUNKDIRS..." <> help "Paths to directories containing thunk data")
-  <*> many (thunkDirArg mempty)
-  where
-    thunkDirArg opts = fmap (dropTrailingPathSeparator . normalise) $ strArgument $ action "directory" <> opts
+  <$> dirArg (metavar "THUNKDIRS..." <> help "Paths to directories containing thunk data")
+  <*> many (dirArg mempty)
 
+createWorktreeArgs :: Parser (FilePath, FilePath)
+createWorktreeArgs = (,)
+  <$> dirArg (metavar "THUNKDIR" <> help "Path to directory containing thunk data")
+  <*> dirArg (metavar "GITDIR" <> help "Path to local git repo")
+
+dirArg :: Mod ArgumentFields FilePath -> Parser FilePath
+dirArg opts = fmap (dropTrailingPathSeparator . normalise) $ strArgument $ action "directory" <> opts
+
 thunkCommand :: Parser ThunkCommand
 thunkCommand = hsubparser $ mconcat
   [ command "update" $ info (ThunkCommand_Update <$> thunkUpdateConfig <*> thunkDirList) $ progDesc "Update packed thunk to latest revision available on the tracked branch"
   , command "unpack" $ info (ThunkCommand_Unpack <$> thunkDirList) $ progDesc "Unpack thunk into git checkout of revision it points to"
+  , command "worktree" $ info (ThunkCommand_Worktree <$> createWorktreeConfig <*> createWorktreeArgs) $ progDesc "Create a git worktree of the thunk using the specified local git repo"
   , command "pack" $ info (ThunkCommand_Pack <$> thunkPackConfig <*> thunkDirList) $ progDesc "Pack git checkout or unpacked thunk into thunk that points at the current branch's upstream"
   , command "create" $ info (ThunkCommand_Create <$> thunkCreateConfig) $ progDesc "Create a packed thunk without cloning the repository first"
   ]
@@ -79,5 +92,6 @@
 runThunkCommand = \case
   ThunkCommand_Update config dirs -> mapM_ (updateThunkToLatest config) dirs
   ThunkCommand_Unpack dirs -> mapM_ unpackThunk dirs
+  ThunkCommand_Worktree config (thunkDir, gitDir) -> createWorktree thunkDir gitDir config
   ThunkCommand_Pack config dirs -> mapM_ (packThunk config) dirs
   ThunkCommand_Create config -> createThunk' config
diff --git a/src/Nix/Thunk/Internal.hs b/src/Nix/Thunk/Internal.hs
--- a/src/Nix/Thunk/Internal.hs
+++ b/src/Nix/Thunk/Internal.hs
@@ -11,6 +11,7 @@
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
 {-# LANGUAGE TypeApplications #-}
 module Nix.Thunk.Internal where
 
@@ -220,6 +221,11 @@
   , _thunkCreateConfig_destination :: Maybe FilePath
   } deriving Show
 
+data CreateWorktreeConfig = CreateWorktreeConfig
+  { _createWorktreeConfig_branch :: Maybe String
+  , _createWorktreeConfig_detach :: Bool
+  } deriving Show
+
 -- | Convert a GitHub source to a regular Git source. Assumes no submodules.
 forgetGithub :: Bool -> GitHubSource -> GitSource
 forgetGithub useSsh s = GitSource
@@ -558,9 +564,9 @@
 
   destination <- case _thunkCreateConfig_uri config of
     ThunkCreateSource_Absolute uri -> pure $ fromMaybe (defaultDestinationForGitUri uri) $ _thunkCreateConfig_destination config
-    ThunkCreateSource_Relative _ ->
-      fromMaybe (failWith "When using a relative path as the thunk source, the destination path must be specified.") $
-        fmap pure (_thunkCreateConfig_destination config)
+    ThunkCreateSource_Relative _ -> case _thunkCreateConfig_destination config of
+      Nothing -> failWith "When using a relative path as the thunk source, the destination path must be specified."
+      Just dst -> pure dst
   createThunk destination $ Right newThunkPtr
 
 createThunk :: MonadNixThunk m => FilePath -> Either ThunkSpec ThunkPtr -> m ()
@@ -607,7 +613,7 @@
                   Just b -> setThunkSourceBranch (Just $ N b) $ _thunkPtr_source t
             rev <- getLatestRev newSrc
             overwriteThunk target $ modifyThunkPtrByConfig (_thunkUpdateConfig_thunk cfg) $ ThunkPtr
-              { _thunkPtr_source = _thunkPtr_source t
+              { _thunkPtr_source = newSrc
               , _thunkPtr_rev = rev
               }
 
@@ -1137,6 +1143,69 @@
   when (_gitSource_fetchSubmodules gitSrc) $
     void $ readGitProcess dir ["submodule", "update", "--recursive", "--init"]
 
+createWorktree :: MonadNixThunk m => FilePath -> FilePath -> CreateWorktreeConfig -> m ()
+createWorktree thunkDir gitDir config = checkThunkDirectory thunkDir *> readThunk thunkDir >>= \case
+  Left err -> failReadThunkErrorWhile "while creating worktree" err
+  Right ThunkData_Checkout -> failWith [i|Thunk at ${thunkDir} is already unpacked|]
+  Right (ThunkData_Packed _ tptr) -> do
+
+    ensureGitRevExist gitDir tptr
+
+    let (thunkParent, thunkName) = splitFileName thunkDir
+    withTempDirectory thunkParent thunkName $ \tmpThunk -> do
+      withSpinner' ("Creating worktree for " <> T.pack thunkName)
+                   (Just (const $ "Created worktree for " <> T.pack thunkName)) $ do
+        currentDir <- liftIO getCurrentDirectory
+        let worktreePath = currentDir </> tmpThunk </> unpackedDirName
+            thunkFullPath = currentDir </> thunkDir </> unpackedDirName
+
+            -- Create a new branch with the user specified name if provided
+            -- else fallback to the branch specified in thunk
+            -- If a local branch already exists in gitDir, the worktree creation will fail
+            -- In which case the user should specify an alternate branch or use "-d"
+            mBranchName = case _createWorktreeConfig_branch config of
+              Just b -> Just b
+              _ -> T.unpack . untagName <$> _gitSource_branch (thunkSourceToGitSource $ _thunkPtr_source tptr)
+
+        _ <- readGitProcess gitDir $
+          [ "worktree", "add"
+          , worktreePath
+          , refToHexString (_thunkRev_commit $ _thunkPtr_rev tptr)
+          ] ++ (if _createWorktreeConfig_detach config
+                then ["-d"]
+                else maybe [] (\b -> ["-b",  b]) mBranchName)
+
+        liftIO $ removePathForcibly thunkDir
+
+        _ <- readGitProcess gitDir
+          [ "worktree", "move"
+          , normalise worktreePath
+          , normalise thunkFullPath]
+        pure ()
+
+-- | Ensures that the git repo contains the revision specified in the ThunkPtr
+-- by doing fetch from remote if necessary.
+ensureGitRevExist :: MonadNixThunk m => FilePath -> ThunkPtr -> m ()
+ensureGitRevExist gitDir tptr = do
+  isdir <- liftIO $ doesDirectoryExist gitDir
+  -- check .git
+  unless isdir $ failWith $ "Git directory does not exist: " <> T.pack gitDir
+
+  (exitCode, _, _) <- readCreateProcessWithExitCode $
+    gitProc gitDir
+      [ "reflog"
+      , "exists"
+      , refToHexString (_thunkRev_commit $ _thunkPtr_rev tptr)
+      ]
+
+  when (exitCode /= ExitSuccess) $ do
+    void $ readGitProcess gitDir
+      [ "fetch"
+      , T.unpack $ gitUriToText (_gitSource_url $ thunkSourceToGitSource $ _thunkPtr_source tptr)
+      , refToHexString (_thunkRev_commit $ _thunkPtr_rev tptr)
+      ]
+
+
 -- | Read a git process ignoring the global configuration (according to 'ignoreGitConfig').
 readGitProcess :: MonadNixThunk m => FilePath -> [String] -> m Text
 readGitProcess dir = readProcessAndLogOutput (Notice, Notice) . ignoreGitConfig . gitProc dir
@@ -1172,8 +1241,18 @@
     (finalMsg noTrail $ const $ "Packed thunk " <> T.pack thunkDir) $
     do
       let checkClean = if force then CheckClean_NoCheck else CheckClean_FullCheck
-      thunkPtr <- modifyThunkPtrByConfig thunkConfig <$> getThunkPtr checkClean thunkDir (_thunkConfig_private thunkConfig)
-      liftIO $ removePathForcibly thunkDir
+      (thunkPtr, isWorktree) <- first (modifyThunkPtrByConfig thunkConfig)
+        <$> getThunkPtr checkClean thunkDir (_thunkConfig_private thunkConfig)
+      if isWorktree
+        then void $ do
+          -- Remove the branch locally, and then remove the worktree
+          case _gitSource_branch $ thunkSourceToGitSource $ _thunkPtr_source thunkPtr of
+            Just branch -> do
+              void $ readGitProcess thunkDir ["switch", "--detach"]
+              void $ readGitProcess thunkDir ["branch", "-d", T.unpack $ untagName branch]
+            Nothing -> pure () -- Should never happen
+          readGitProcess thunkDir ["worktree", "remove", "."]
+        else liftIO $ removePathForcibly thunkDir
       createThunk thunkDir $ Right thunkPtr
       pure thunkPtr
 
@@ -1193,14 +1272,22 @@
   | CheckClean_NoCheck
   -- ^ Don't check that the repo is clean
 
-getThunkPtr :: forall m. MonadNixThunk m => CheckClean -> FilePath -> Maybe Bool -> m ThunkPtr
+getThunkPtr :: forall m. MonadNixThunk m => CheckClean -> FilePath -> Maybe Bool -> m (ThunkPtr, Bool)
 getThunkPtr gitCheckClean dir mPrivate = do
   let repoLocations = nubOrd $ map (first normalise)
         [(".git", "."), (unpackedDirName </> ".git", unpackedDirName)]
   repoLocation' <- liftIO $ flip findM repoLocations $ doesDirectoryExist . (dir </>) . fst
-  thunkDir <- case repoLocation' of
-    Nothing -> failWith [i|Can't find an unpacked thunk in ${dir}|]
-    Just (_, path) -> pure $ normalise $ dir </> path
+  (thunkDir, isWorktree) <- case repoLocation' of
+    Nothing -> do
+      ff <- liftIO $ flip findM repoLocations $ doesFileExist . (dir </>) . fst
+      case ff of
+        Nothing -> failWith [i|Can't find an unpacked thunk in ${dir}|]
+        Just (gitPath, path) -> do
+          putLog Informational "Couldn't find .git dir, looking for a worktree instead"
+          fileContents <- liftIO $ T.readFile (dir </> gitPath)
+          unless (T.isPrefixOf "gitdir: " fileContents) $ failWith [i|Can't find an unpacked thunk or worktree in ${dir}|]
+          pure (normalise $ dir </> path, True)
+    Just (_, path) -> pure (normalise $ dir </> path, False)
 
   let (checkClean, checkIgnored) = case gitCheckClean of
         CheckClean_FullCheck -> (True, True)
@@ -1210,7 +1297,7 @@
     "thunk pack: thunk checkout contains unsaved modifications"
 
   -- Check whether there are any stashes
-  when checkClean $ do
+  when (checkClean && not isWorktree) $ do
     stashOutput <- readGitProcess thunkDir ["stash", "list"]
     unless (T.null stashOutput) $
       failWith $ T.unlines $
@@ -1230,12 +1317,16 @@
         ]
       _ -> return (b, c)
 
-  -- Get information on all branches and their (optional) designated upstream
-  -- correspondents
+  let refs = if isWorktree
+        -- Get information on current branch only
+        then "refs/heads/" <> maybe "" T.unpack mCurrentBranch
+        -- Get information on all branches and their (optional) designated
+        -- upstream correspondents
+        else "refs/heads/"
   headDump :: [Text] <- T.lines <$> readGitProcess thunkDir
     [ "for-each-ref"
     , "--format=%(refname:short) %(upstream:short) %(upstream:remotename)"
-    , "refs/heads/"
+    , refs
     ]
 
   (headInfo :: Map Text (Maybe (Text, Text)))
@@ -1291,15 +1382,17 @@
     -- branch. Purely being behind is fine.
     let nonGood = Map.filter ((/= 0) . fst . snd) stats
 
-    when (not $ Map.null nonGood) $ failWith $ T.unlines $
-      [ "thunk pack: Certain branches in the thunk have commits not yet pushed upstream:"
-      , ""
-      ] ++
-      flip map (Map.toList nonGood) (\(branch, (upstream, (ahead, behind))) -> mconcat
-        ["  ", branch, " ahead: ", T.pack (show ahead), " behind: ", T.pack (show behind), " remote branch ", upstream]) ++
-      [ ""
-      , "Please push these upstream and try again. (Or just fetch, if they are somehow \
-        \pushed but this repo's remote tracking branches don't know it.)"
+    when (not $ Map.null nonGood) $ failWith $ T.unlines $ mconcat
+      [ [ "thunk pack: Certain branches in the thunk have commits not yet pushed upstream:"
+        , ""
+        ]
+      , [ "  " <> branch <> " ahead: " <> T.pack (show ahead) <> " behind: " <> T.pack (show behind) <> " remote branch " <> upstream
+        | (branch, (upstream, (ahead, behind))) <- Map.toList nonGood
+        ]
+      , [ ""
+        , "Please push these upstream and try again. (Or just fetch, if they are somehow \
+          \pushed but this repo's remote tracking branches don't know it.)"
+        ]
       ]
 
   when checkClean $ do
@@ -1308,7 +1401,7 @@
 
   let remote = maybe "origin" snd $ flip Map.lookup headUpstream =<< mCurrentBranch
 
-  [remoteUri'] <- fmap T.lines $ readGitProcess thunkDir
+  [remoteUri'] <- T.lines <$> readGitProcess thunkDir
     [ "config"
     , "--get"
     , "remote." <> T.unpack remote <> ".url"
@@ -1317,7 +1410,7 @@
   remoteUri <- case parseGitUri remoteUri' of
     Nothing -> failWith $ "Could not identify git remote: " <> remoteUri'
     Just uri -> pure uri
-  uriThunkPtr remoteUri mPrivate mCurrentBranch mCurrentCommit
+  (, isWorktree) <$> uriThunkPtr remoteUri mPrivate mCurrentBranch mCurrentCommit
 
 -- | Get the latest revision available from the given source
 getLatestRev :: MonadNixThunk m => ThunkSource -> m ThunkRev
@@ -1335,7 +1428,7 @@
 uriThunkPtr :: MonadNixThunk m => GitUri -> Maybe Bool -> Maybe Text -> Maybe Text -> m ThunkPtr
 uriThunkPtr uri mPrivate mbranch mcommit = do
   commit <- case mcommit of
-    Nothing -> gitGetCommitBranch uri mbranch >>= return . snd
+    Nothing -> snd <$> gitGetCommitBranch uri mbranch
     (Just c) -> return c
   (src, rev) <- uriToThunkSource uri mPrivate mbranch >>= \case
     ThunkSource_GitHub s -> do
