24

I have a local repository that is a full copy of a repository on Github. I made a change that I would like to contribute to the original project.

How can I do this without reloading my project on Github? I don't think opening an issue is the right way..

I saw in How can I contribute a patch to github? that I should fork the project, but since my local repository is "linked" to the original Github repository, I don't want to mess it up.

So, if it is really discouraged to share the patch in any way but fork, how can I simply fork the original project, merge my changes, and then share them with the original repository?

If I delete the fork after I "committed" the change but it isn't accepted yet, does my commit disappear?

Community
  • 1
  • 1
Makers_F
  • 3,033
  • 4
  • 36
  • 51

4 Answers4

20

You should fork the project, yes. However, this does not mean you need to clone the whole stuff again locally.

Explanation: a simple way of looking at a git repository is a graph of commits (it is directed and acyclic but that is irrelevant for this discussion); and all nodes of this graph, ie the commits, have a unique identifier across all git repositories in the world. As to branches, they are just symbolic references to a commit (in git parlance, a branch -- or a tag -- is called a refspec).

Also, you are never linked to a remote repository in any way. The only thing you are really "linked to" is the commit graph. A remote repository just happens to have a set of refspecs (branches, tags)... pointing to a commit graph, which they also have -- nobody likes dangling references. When you clone a repository, you get the commit graph (and associated trees) and the set of refspecs (ie branches, tags). A refspec points to a tree. And that's about it.

This means the following:

  • you have the original github repo: a graph of commits and associated trees, a set of refspecs;
  • you have cloned it locally: the same graph of commits and associated trees, the same set of refspecs;
  • you have committed stuff locally: you have added upon this graph and associated trees, and added a new set of refspecs.

OK, now do the following:

  • clone the original repo on github: the same graph of commits and trees as the original; the refspecs are here, only preceded with the remote name, which is origin by default. And what now?
  • on your local repository, add your fork as a remote;
  • push to that fork (this will push the refspecs, and trees);
  • submit a pull request.

Adding your fork as a remote is as "simple" as:

git remote add myfork git@github.com:youruser/theproject

Push your refspec (branch) to it:

git push myfork mybranch

And then submit a pull request to the original author.

It should be noted that in theory, you can add a remote to a git repository which has no relevance at all with the "original" repo: this is simply that the two commit graphs will be completely disjoint from one another -- however, the use cases for this are rare

fge
  • 119,121
  • 33
  • 254
  • 329
  • 1
    "Nobody ever does that" -- I do that sometimes, when I want to merge two entire projects, retaining the full history for both. – Fred Foo Jan 14 '12 at 22:21
  • Also, there's no need for the `git fetch`. – Fred Foo Jan 14 '12 at 22:34
  • @larsmans points taken... Let's say that "nobody ever does that" could be replaced with "the use cases for this are rare"? – fge Jan 14 '12 at 22:57
  • I'll admit that it's "advanced usage" (or "arcane Git magic" :) – Fred Foo Jan 14 '12 at 22:58
  • Can i delete the fork after the i pulled the change, even if it isn't accepted yeet? Btw I had a bit of problems, since i didn't know how to remove a commit i made a lot of time ago that i didn't want to share(it was just a few options in the project file, so it shouldn't be changed on the original one). At the end i pulled everything, providing in the comment the link to the diff with only the right commit. Btw this way is far more complex that simply sharing .diff or .patch.. – Makers_F Jan 14 '12 at 23:24
  • To remove a commit you made "a long time ago", you'd have to know the SHA1 of a commit which didn't have it, and then use `git rebase -i` to remove that commit. – fge Jan 15 '12 at 01:15
  • To add to the previous comment, do NOT do "git rebase -i" if that includes commits by other people, read [this](http://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase) for details. In this case, I'd save the current work in a new branch, do a reset of master, and cherry-pick the relevant commits back. – dequis Jun 22 '13 at 04:04
  • 1
    Okay... so I did all this -- I'm showing the change in my fork on GitHub... still not sure how to "Submit" it -- on the project's main github I went to pull requests, and clicked "new pull request"... then I press "compare across forks", I select the main fork and master on the left and my fork and the branch with the changes on the right... and then what? There's no "submit" or "save" or "okay" button, or anything. What am I missing? – BrainSlugs83 Sep 02 '13 at 03:26
  • Where does mybranch come from? I did nothing to create it and I'm getting `error: src refspec mybranch does not match any.` – kuzzooroo Apr 30 '15 at 01:26
6

Yes, you should fork the project, but there's no need to clone/pull/merge anything. After you click the fork button, do

git remote add yourfork git@github.com:<yourname>/<project>.git

and push your branch to your fork with

git push yourfork branchname

then issue a pull request.

If you delete the fork after the patch is merged by upstream, there should be no problem. I'm not sure what happens when you remove your fork before that happens.

There's no need to merge anything.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
2

You can always send a patch file to the maintainer by e-mail. The Linux kernel has been crafted that way for a very long time.

greut
  • 4,305
  • 1
  • 30
  • 49
0

Without fiddling with your current copy of the repository.

  • Create the patches with format-patch.
  • Fork upstream and clone it, but don't replace your working copy.
  • Apply the patches with git am to the newly forked project, push them and create the merge request.

This is not the nicest solution, but it prevents you from accidentally loosing your changes.

usr1234567
  • 21,601
  • 16
  • 108
  • 128