How to designate a local repository as a remote for another local repository?
In order to better understand how Git works, I’d like to inspect the changes that a remote repository undergoes as it interacts with a local repository (via fetch, push, etc.).
Suppose I have two Git repositories, A and B, in my local file system. Is it possible to designate A as a remote repository with respect to B, so that, for instance all
pushcommands performed in B will be pushed to A?
- performing git push with repo URL pre set
- git rebase -i a branch onto itself
- Github API for Python : PyGithub - get a list of all commits for a particular repository
- feasibility of git without a remote repo
- Git log: list all parents commits
- Rebuild loose missing tree in Git when there are no other missing objects
Is it possible to clone a new local repository C from A using the
2 Solutions collect form web for “How to designate a local repository as a remote for another local repository?”
The answer to both your questions is: Yes!
Use the Git commands as usual and pass the full or the relative path of the other repository as argument
For example, use:
git clone ../repoA repoB
to clone the repository
../repoA into the sub-directory
repoB of the current directory.
Read more about the ways to specify an URL in Git commands that require an URL of a remote repository.
All Git repositories are peers, as far as Git itself is concerned. Furthermore, any repository is at least logically entirely self-contained (there are some tricky things you can do with “alternate object locations” that makes them physically interdependent, but let’s ignore that for now).
Suppose I have two Git repositories, A and B, in my local file system. Is it possible to designate A as a remote repository with respect to B, so that, for instance all push commands performed in B will be pushed to A?
Back this up for a moment and let’s look at the definition of remote. The term is somewhat overloaded (we can talk about a “remote peer” or “a Git at some remote host”, for instance), but each Git repository defines, through its own local configuration file (
git config), some number—possibly zero—of remotes.
A remote is just a name, like
origin or, in our case,
A. The name becomes part of slightly longer names that are used as key/value pairs:
another value, and so on.
So, in repository B, we can define a remote named
A, setting some of these key/value pairs. At least one key/value pair is required (so that the
[remote "A"] section gets created), and a
url setting is appropriate here:
cd B git config remote.A.url <some url here>
B now has a remote named
A. The URL can be just a simple path, or
ssh://host.name/path/to/repo.git, or something starting with
The URL needs to reach a Git that can read and/or write the other repository. If the URL is a local file system path, your own Git plays both roles, but at least logically, it pretends to talk to a separate Git that represents the other repository.
remote.A entry is pretty important if
B will ever run
git fetch to read from
A. This will supply the default refspec, which would generally be:
git config --add remote.A.fetch '+refs/heads/*:refs/remotes/A/*'
Note that there may be multiple
fetch refspecs defined this way (which is a reason to use
--add here). While you are in repository
B, if you now run either
git fetch or
git push and use the name
A as the remote, your Git will call up another Git that will send objects from
A (if you are fetching) or receive objects destined for
A (if you are pushing).
Note that the default fetch refspec or refspecs comes from
git config --get-all remote.A.url, but the default push refspec or refspecs are more complicated (depend on
push.default, and/or if they are set,
There is also an optional
remote.A.pushurl setting. If this is set,
git push A connects not to the
remote.A.url address, but rather to the
(There is also
remote.pushDefault: if you run
git push with no remote specified, the
remote.pushDefault overrides the current branch’s
branch.branch.remote setting, but not its
branch.branch.pushRemote setting. This is all pretty crazy complicated and the only way to keep track is to consult the
git config documentation.)
Note that you don’t have to use a named remote here at all! You can:
git fetch <url> <refspec>
git push <url> <refspec>
The benefit to using a named remote like
A is that you gain all these configuration entries that do fancy things for you, such as remember complicated URLs and complicated default refspecs. Moreover, this enables you to do:
git config branch.evil.remote A git config branch.zorg.remote A
which means that whenever you are on branches
zorg, your Git should connect, by default, to remote
A. Combine this with a
url setting and a default
fetch setting to set up remote-tracking branches in the
refs/remotes/A/ name-space, and you get a convenient way to talk to the remote Git, whether it is “very remote” (on another machine entirely) or “not at all remote” (on your own machine)—though the fancy remote-tracking branch stuff is obviously much less important for a not-at-all-remote remote.
branch.name.remote setting is half of the job of configuring the upstream for that branch. The other half is done by configuring
git branch --set-upstream-to=A/zorg, as you might do on your branch
zorg, sets both at once.)
Is it possible to clone a new local repository C from A using the clone command?
Yes: the syntax for
git clone is
git clone [ options ] url [ directory ]. The URL can, as before, just be a simple path name. If it is, this enables the
--local option by default.
Cloning a repository automatically creates a remote in the new Git repository. This remote is named
origin by default, and has two default settings:
remote.origin.url = <url> remote.origin.fetch = +refs/heads/*:refs/remotes/origin/*
which are of course the recommended settings for any remote. Note that the right hand side of the refspec value of the
fetch setting embeds the name of the remote in it: here it’s
origin, while for
remote.A.fetch it was
… I’d like to inspect the changes that a remote repository undergoes as it interacts with a local repository (via fetch, push, etc.).
There really is no “etc”: fetch and push are it. You can run
git ls-remote and
git remote show, and those two can connect one Git to another, but they do not interact at that point: these just obtain public references and either print them out (
git ls-remote) or compare them to settings in your local repository (
git remote show).
The “obtain public references” step is the first—well, second, perhaps—step in
git fetch and
git push as well, since your Git (you are the one running or push) wants to decide what to fetch or what to push, and these tend to require knowing what references exist in the other Git. (Push seems like it might not care what “they” have, but it does for
matching and for
simple, at least. The first step, if you want to call this the second step, is establishing common protocol capabilities, which is something all the “smart” transports do, since the protocol has evolved somewhat over time.)