26

I added a subtree on git which seems to be working. I went into the directory and made some changes and then pushed.

I noticed these changes show up in the parent project but the repository which I used as the source hasn't been updated.

I tried git subtree push which returns:

You must provide the --prefix option.

Also git subtree push --prefix=my/folder git@mygitrepo.com which returns:

You must provide <repository> <ref>

What is the correct way to push changes to the origin repo for my git subtree?

Edit: it was suggested that I do:

git subtree push --prefix=my/folder origin master

When I run the above it starts the process but ends up saying the branch is behind. So I run:

git subtree pull --prefix=my/folder origin master

Which returns "Already up to date"

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
  • You never mention doing a `commit` (which normally comes between making changes and pushing). Did you commit those changes to the subtree? – crashmstr Feb 03 '17 at 14:59
  • @crashmstr I commited the changes to the parent project, do I have to commit with the subtree command too? – Philip Kirkbride Feb 03 '17 at 15:00
  • Have you tried like this: `git subtree push origin master`? (Or whatever youre remote and the branch are called) – Dan Feb 03 '17 at 15:01
  • @Dan I hadn't but I'm trying now and I get "you must provide the --prefix option" – Philip Kirkbride Feb 03 '17 at 15:02
  • Oops, I was thinking submodule (which I have worked with) instead of subtree (which I have not worked with). – crashmstr Feb 03 '17 at 15:04
  • @PhilipKirkbride Well, then do provide that too: `git subtree push --prefix=my/folder origin master` – Dan Feb 03 '17 at 15:05
  • @Dan thanks this got me a bit further. I posted results in my question as an edit. – Philip Kirkbride Feb 03 '17 at 15:11
  • @PhilipKirkbride Why are you doing a `pull` this time instead of a `push`? Btw there's no issue in the latter reply from `git`: it just tells you, your local is up to date with the remote. – Dan Feb 03 '17 at 15:14
  • @Dan I ran push and it said my repository was behind, so I ran pull which said it was up to date. – Philip Kirkbride Feb 03 '17 at 15:15
  • @PhilipKirkbride I see. Sorry, I missed that point. What exactly did it say? I assume it was behind, so it pushed, and now it's up to date. I don't really know all the details of you repo, but have a look at whether they are in sync. Try to use `git log`. – Dan Feb 03 '17 at 15:22
  • @Dan I wish there was a 'git subtree log' command. – Philip Kirkbride Feb 03 '17 at 15:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/134786/discussion-between-dan-and-philip-kirkbride). – Dan Feb 03 '17 at 15:32

3 Answers3

32

So, with some joint effort with @PhilipKirkbride, here's what we managed to figure out:

You need to put all the details in the command:

git subtree push --prefix=my/folder subtree_origin master

Where master is the branch in the subtree, and subtree_origin is just another remote, which happens to point to your subtree's git repository. You can also type the full repo URL.

Dan
  • 630
  • 5
  • 8
0

With Git 2.32 (Q2 2021), Dan's 2017 answer can be applied to any commit, not just HEAD.

See commit 9a3e3ca, commit 49470cd, commit 94389e7, commit cb65514, commit 6468784, commit e9525a8, commit 534ff90, commit 5cdae0f, commit cbb5de8, commit e4f8baa, commit bbffb02, commit 22d5507, commit a94f911, commit e2b11e4, commit 6d43585, commit f664304, commit 8dc3240, commit d2f0f81, commit 5a35697, commit b04538d, commit b269976, commit db6952b, commit f1cd2d9, commit 63ac4f1, commit c4566ab, commit 40b1e1e, commit f700406, commit f2bb7fe, commit 914d512, commit 4c996de (27 Apr 2021) by Luke Shumaker (LukeShu).
(Merged by Junio C Hamano -- gitster -- in commit 44ccb76, 10 May 2021)

subtree: push: allow specifying a local rev other than HEAD

Signed-off-by: Luke Shumaker

git subtree split lets you specify a rev other than HEAD.
'git push'(man) lets you specify a mapping between a local thing and a remot ref.

So smash those together, and have git subtree push let you specify which local thing to run split on and push the result of that split to the remote ref.

git subtree man page now includes:

push <repository> [+][<local-commit>:]<remote-ref>

Does a 'split' using the subtree of <local-commit> and then does a 'git push' to push the result to the <repository> and <remote-ref>.

This can be used to push your subtree to different branches of the remote repository.
Just as with 'split', if no <local-commit> is given, then HEAD is used.
The optional leading '+' is ignored.

That means this will work:

git subtree push --prefix="sub dir" --annotate="*" ./"sub proj" HEAD^:from-mainline
                                                                ^^^^^^

With Git 2.33 (Q3 2021), git subtree actually works on Windows.

See commit 77f37de, commit f7ee88f (14 Jun 2021) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit e22ac8b, 08 Jul 2021)

subtree: fix the GIT_EXEC_PATH sanity check to work on Windows

Signed-off-by: Johannes Schindelin

In 22d5507 ("subtree: don't fuss with PATH", 2021-04-27, Git v2.32.0-rc0 -- merge listed in batch #15), git subtree was broken thoroughly on Windows.

The reason is that it assumes Unix semantics, where PATH is colon-separated, and it assumes that $GIT_EXEC_PATH: is a verbatim prefix of $PATH.
Neither are true, the latter in particular because GIT_EXEC_PATH is a Windows-style path, while PATH is a Unix-style path list.

Let's make extra certain that $GIT_EXEC_PATH and the first component of $PATH refer to different entities before errorring out.

We do that by using the test <path1> -ef <path2> command that verifies that the inode of <path1> and of <path2> is the same.

Sadly, this construct is non-portable, according to test utility.
However, it does not matter in practice because we still first look whether $GIT_EXEC_PREFIX is string-identical to the first component of $PATH.
This will give us the expected result everywhere but in Git for Windows, and Git for Windows' own Bash does handle the -ef operator.

Just in case that we do need to show the error message and are running in a shell that lacks support for -ef, we simply suppress the error output for that part.

This fixes git-for-windows/git issue 3260


With Git 2.35 (Q1 2022), git subtree (in contrib/) is faster.

See commit 3ce8888 (08 Dec 2021) by James Limbouris (jamesl-dm).
(Merged by Junio C Hamano -- gitster -- in commit 9b6eda0, 10 Jan 2022)

subtree: fix argument handling in check_parents

Signed-off-by: James Limbouris

315a84f ("subtree: use commits before rejoins for splits", 2018-09-28, Git v2.20.0-rc0 -- merge listed in batch #6) changed the signature of check_parents from 'check_parents [REV...]' to 'check_parents PARENTS_EXPR INDENT'.
In other words the variable list of parent revisions became a list embedded in a string.
However it neglected to unpack the list again before sending it to cache_miss, leading to incorrect calls whenever more than one parent was present.
This is the case whenever a merge commit is processed, with the end result being a loss of performance from unecessary rechecks.

The indent parameter was subsequently removed in e9525a8 ("subtree: have $indent actually affect indentation", 2021-04-27, Git v2.32.0-rc0 -- merge listed in batch #15), but the argument handling bug remained.

For consistency, take multiple arguments in check_parents, and pass all of them to cache_miss separately.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
-1

normally the output dir, such as dist or public are ignored in the .gitignore. If you want to use git subtree on these paths, you have to

git add <DIR to be subtree pushed>

then git commit.

When finished above two steps, you are okay to git subtree push those generated dir into a separate branches of your repository.

Cross
  • 700
  • 1
  • 8
  • 22