On Thu, Jun 21, 2018 at 05:48:28PM -0700,
jeff....@intexx.com wrote:
Hi, Jeff!
> I'm running into problems keeping a second repo mirrored with the first, as
> detailed here <
https://stackoverflow.com/q/50978056/722393>.
>
> I've since tried completely deleting and recreating from scratch both R1
> and R2 repos, but curiously that doesn't help. It seems no matter what I do
> and how I do it, R1 refuses to send new changes to R2.
>
> Is there a way to troubleshoot this? (Caution: Git beginner on the loose.)
(For a start, next time please take your time to actually copy-and-paste
stuff from the original place so everyone has the context to quote in
their replies. Also please note that many people are just lazy to follow
links or read their mail in a MUA while disconnected from the 'net.)
For me, the situation is somewhat complex to comprehend extensively, and
the fact you appear to use non-vanilla Git on your remotes (I have no
clear idea what is TFS and VSTS — besides the fact these are some
tools from Microsoft to do version control). Still, let's try to may be
at least move you a bit further in your quest. ;-)
For a start the pictures for "R1 state" [1] and "R2 state" [2] sadly do
not say anything about which _branch_ was considered on it.
By correlating what's on the images with what's on the captures of the
`git push` commands run, I guess you were looking at either "master" or
"Application/master".
I'm going to offer two insights on how to approach the situation.
First, I think you might have a wrong mental model of how branches
(and everything else) is managed in Git — especially when there are
both regular repos (those used on workstations, supposedly what you have
at W) and bare repos (those used on servers, supposedly what you have on
R1 and R2).
Since Git is a distributed VCS, each Git repo is completely
free-standing — in the sense it does not depend on any other repo, and
any "linking" between different repos — in the form of "remote repos" —
is merely a policy thing.
This means, even if names are the same, a branch "master" in a local
repository does not in any way inherently depend on the same-named
branch in any other repository you are able to fetch from or push to.
In W, you appear to have a remote named "origin" — which is typically
created by `git clone` when you clone an already existing repository
(that's why it called "origin" after all).
For remote repositories, Git typically manages a set of so-called
"remote branches". Remote branches are best thought of as "bookmarks"
to the state of the branches as found in their remote repository the
last time it was fetched from. Git has certain helpers in place which
allow your local braches — those you actually work on — to be linked
with certain remote branches. If a local branch is linked this way with
a remote branch, it is said the local branch "tracks" the remote branch.
As the most common example of this, after fetching all the data, the
`git clone` command typically creates a single local branch "master"
pointing at the just-created remote branch "origin/master", and makes
the local "master" track "origin/master".
Suppose you now run `git fetch origin` — Git will fetch everything the
local repository does not yet have, and if the branch "master" was
updated in the remote repo (compared to the state of "origin/master"
locally), the "origin/master" remote branch will be updated to match
that state. (Note this will make nothing with the local "master"
branch — as I've said, all this linking is a policy thing because you
may have any number of remote repositories to contact with, and each of
them is free to has its own branch "master".)
If you so wish, you might now consider integrating what's there in
"origin/master" into your local "master" — in one way or another.
You might merely merge "origin/master" into "master", or rebase "master"
on "origin/master" or whatever.
When you push your local "master" to update "master" in the remote
repository known as "origin", Git also updates the "origin/master"
bookmark.
I highly recommend to read and absorb [3] to get a firm grasp on this
idea.
So, we're going to arrive at the first point I wanted to highlight:
if you want to _mirror_ W to R1 — as in rewrite everything at R1
with whatever there is on W, — there's no point in using
`git push --mirror`: it also sends your remote branches to the remote
repository which has quite little sense and may confuse you when you
look at R1.
A better approach is to drop "--mirror" and use explicit "refspecs"
for `git push` telling it to force-push all the branches and tags,
and also remove at the remote the branches which names match those
of the branches deleted locally:
git push --force --prune --tags origin "refs/heads/*:refs/heads/*"
It's like `git push --mirror origin` but omits the hierarchy
'refs/remotes/origin/*' from pushing.
Before or after switching to this new approach you should possibly get
rid of the pushed remote branches in both R1 and R2 — to lessen the
amount of cruft in them. You can do this by running
git push ":refs/remotes/*"
Not pushing the remote branches would get rid of those "origin/..."
thingies in
| POST git-receive-pack (744 bytes)
| Pushing to
https://Personal%20Access%20Token: [...]
| To
https://customer.visualstudio.com/Applications/_git/Application
| = [up to date] master -> master
| = [up to date] origin/develop -> origin/develop
| - [deleted] Application/master
| c13bdc5..81ddbe0 origin/master -> origin/master
| updating local tracking ref 'refs/remotes/Application/master'
See [4] for more info.
The second point I'd like to make is that there exists useful commands
which allow to _directly_ check what's there in any given remote
repository. This may help enormously to rule out possible problems you
may have with inspecting the state of R1 and R2 using whatever
TFS- and VSTS-native things exists for this.
The first one is `git ls-remote <URL_or_remote_name>` which contacts the
remote repository, asks it to tell what it has and lists that in the
form of pairs "commit hash + ref name".
For example:
| $ git ls-remote fork
| 8fed8eb1c43d9c97bd5157a8760658438a0b3bd6 HEAD
| 8fed8eb1c43d9c97bd5157a8760658438a0b3bd6 refs/heads/kaboom
| 8fed8eb1c43d9c97bd5157a8760658438a0b3bd6 refs/heads/master
So you may easily verify two things:
- The remote repo of interest does really have a branch of interest.
- The tip commit of that branch is expected.
(Note that Git call everything which can be "named" "a ref", which is
short for "reference", and the internal term for branch is "head".
That's why branches live in the "refs/heads/" namespace, and tags
live in "refs/tags".)
Another — more high-level — command is
$ git remote [-v] show <remotename>
It does not show you commit names but it lays out which, if any,
tracking policies are configured for the local branches against that
remote.
So, I'd go this way:
1) Switch to not using "full-mirror" pushing for W->R1 updates.
2) Delete all remote branches pushed from W to R1.
3) Afterwards, use `git ls-remote` to verify the contents of R1
is expected as compared to the set of local branches in W.
4) When synchronizing R1 to R2, make sure the remote branches "poisoned"
R1 from W are also deleted in R2 (in theory, plain
`git push --mirror` should take care of that; if not, you may use
that "push nothing" call I shown before to take care of that).
5) Use `git ls-remote` to verify R2 really mirrors the state of R1.
To see which branches the local repository has, and at which commits
they point, use something like
git branch --list -v --no-abbrev
You might also throw in "--all" or "--remote" to see local _and_ remote
branches or only the remote branches.
1.
https://i.stack.imgur.com/o7dkK.png
2.
https://i.stack.imgur.com/yGg8C.png
3.
https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches
4.
https://public-inbox.org/git/xmqqpoec...@gitster.mtv.corp.google.com/t/