我对我创建的场景很困惑。我在Github上创建了一个存储库(让我们称之为A)并将代码推送到它。之后我将该存储库克隆到我的本地(让我们称之为B),这样我本地的来源就是远程回购A.
现在我从我的本地B克隆来创建另一个本地实例C.现在我有远程起源的C作为repo B而C的上游是A。
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import org.apache.commons.lang.math.NumberUtils;
public class RestServiceFilter implements ContainerRequestFilter {
private static Logger _logger = Logger.getLogger(RestServiceFilter.class.getName());
@Override
public void filter(ContainerRequestContext crc) {
_logger.info("***** REST FILTER*********************");
crc = updateURLForVersion(crc);
}
private ContainerRequestContext updateURLForVersion(ContainerRequestContext cr) {
String baseURI = cr.getUriInfo().getBaseUri().toString();
String requestURI = cr.getUriInfo().getRequestUri().toString();
String pathURI = requestURI.substring(baseURI.length(), requestURI.length());
String version = null;
if (pathURI.startsWith("v") && pathURI.contains("/")) {
String versionInURL = pathURI.substring(1, pathURI.indexOf("/"));
if (NumberUtils.isNumber(versionInURL)) {
version = "v" + versionInURL;
}
}
if (StringUtil.isNullOrEmpty(version)) {
version = ConfigReader.getinstance().get(Constants.REST_LATEST_VERSION);
pathURI = version + "/" + pathURI;
requestURI = baseURI + pathURI;
try {
cr.getUriInfo().getRequestUriBuilder().replacePath(requestURI);
// cr.setRequestUri(new URI(requestURI));
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(RestServiceFilter.class.getName()).log(Level.SEVERE, null, ex);
}
}
return cr;
}
这类似于分叉,但在这里我在客户端而不是服务器端创建了克隆。
现在,如果我尝试使用从C推送到其原点B:
A → B → C
然后我收到一条错误,指出我无法推送到非裸存储库。我知道推送到非裸存储库可能会导致本地远程不存在的提交丢失。
然而,这种情况与我将代码从B推送到A的情况不相似吗?
我很困惑,如果B到A是可能的,那么为什么不是C到B.
对于合并到A,我们可以推送到上游:
git push origin
答案 0 :(得分:6)
从开发人员的角度来看,只要您git clone
,您就会想要处理刚刚克隆的代码。因此GIT为您提供了一个工作树"努力工作。它被称为树,因为当你考虑所做的所有提交和分支并将其放在图表上时,它就像一棵树。
克隆的存储库称为非裸存储库。要创建一个非裸存储库,您可以执行一个简单的git init
- 这是原始程序员用GIT开始跟踪克隆代码所做的工作。您也可以将其克隆到裸存储库中,但它的详细信息和实用性应该是另一个问题的答案。
裸存储库不包含工作树。它仅用于存储您的代码 - 如果您愿意,可以存储由GIT管理的代码的服务器。要创建一个裸存储库,您可以执行简单的git init --bare name_of_repository.git
。它将创建一个名为name_of_repository.git的目录,其中包含GIT所需的所有文件。 git 扩展名只是一个使用的约定;它不是必需的,可以是任何东西或什么也不是。
GIT中有一个类似指针的东西叫做 HEAD 。它指向在您工作的分支中处于活动状态的最新提交,无论是裸存储库还是非裸存储库。
分支机构就像是不同的副本'您刚刚从远程存储库中提取的代码(可能有不同的修改)。它有开发人员认为合适的任何名称。它们非常有用,因为您可以处理不同的功能或修复不同的问题,而无需担心您或其他人正在开发的当前代码。稍后,您始终可以将所有内容合并到主分支中 - 通常是 master - 然后删除那些不再需要的合并分支。
GIT尝试 最佳以避免不同位置或分支机构的文件版本之间的问题 。所以他不允许你git push
在某些情况下确定混乱至少可以说。 GIT永远不会错,因为它会要求您检查,更改或强制执行您正在执行的操作。所以任何错误都不会成为GIT的错,但仅限你的。
让我们考虑以下几点:
话虽如此,我们假设您修改了B中的一些文件。您可以git commit
多次执行此操作,最后只需git push
。或者你根本不做任何事情。但是你在主分支机构。
稍后,你修改C中的文件。你确实提交并尝试推送到A.记住:你在C的主分支上。git push
有效!
然后,您也尝试将C推送到B. 它没有用。
结果:GIT将(不)字面上尖叫,警告您正在尝试玷污(更新)主分支HEAD指向另一个提交的非裸存储库B!如果他允许你进行推动,你将把GIT跟踪的历史记录弄乱在存储库B上。它不再知道B发生了什么!您甚至可能使用驻留在B上的相同名称覆盖该分支上的修改!所以不,如果两者都是非裸存储库,你就不能推送到B形式C!
现在怎么办?!我的世界会这样结束吗?!伟大的我做了什么?! GIT怎么可能忽视他的主人的意愿?!这是纯粹的异端邪说!
1 - 在B上有两个分支 - 主分支和临时分支。并将头指向临时分支。例如:
cd B # change to B's working directory
git branch temp # create 'temp' branch
git checkout temp # change from master branch to branch temp
2 - 现在,转到C工作目录(简称 wd )并使用B的内容进行操作。请注意,我认为B是远程的C(正如你在案例中提到的):
cd ../C # change to C's working directory
git pull B master # pulls B's modifications to C
3 - 用C修改你的文件。注意你在C&C的主分支上。然后,在提交C的修改后,将其推送到B的主人:
git push B master # pushes C's mods to B's master branch
4 - 现在返回B wd 并将HEAD指向主分支:
cd ../B # change to B's working directory
git checkout master # change from temp branch to branch master
5 - 如果你不再使用它,你可以删除临时分支:
git branch -d temp # delete branch temp
6 - 如果您在C中进行了新的修改,则不需要同时执行步骤4和5.如果您这样做,只要您希望在C中进行修改,你需要事先做好第1步和第2步。
这解决了您的问题! 可能 ......
git branch name_of_the_branch
创建一个新分支; git checkout name_of_the_branch
使HEAD指向这个新分支; git checkout -b name_of_the_branch
创建一个分支,并使HEAD指向一个命令。我使用较长的方法,因为你应该知道更长的方法; 答案 1 :(得分:0)
如果您使用
git clone --bare http://github.com/xxx/A B
然后你可以从C推到B.你当然不会 使用B进行工作,因为它是裸露的。
我仍然不明白为什么你想要“额外的”B回购?