4 ms·
A key point with git is that every clone is effectively its own set of branches; even if they have the same name. The mechanisms you use for synchronizing your
by jillesvangurp 3y ago
A key point with git is that every clone is effectively its own set of branches; even if they have the same name. The mechanisms you use for synchronizing your local branches with some remote branches are exactly the same as the mechanisms you use between to your local named branches.
Git was actually designed initially for email based workflows where there was no central remote at all. Basically, that works by exporting patches and then applying them to your local branch. The branch name isn't even part of the patch.
A git patch is just a textualized form of the list of commits you created locally. You can apply them to any branch you like. As long as you and whomever applies the patch has a common ancestor commit in common, the patch may merge cleanly. It's good hygiene to ensure it does by for example rebasing/merging/squashing before you email somebody your patches. If that somebody is called Linus Torvalds, he's going to be pretty strict about things like commit messages and things not being spaghetti ball of merges, reverts, forks, etc. Your mess, your problem. Linux development still works via mailing list. And forget about emailing him directly with a patch; you need to use the mailing lists like everybody else. And he works with a network of senior contributors that screen everything that comes in and that aggregate all the patches coming from upstream. So, he only gets involved at the end of the process.
Of course the rest of us use network protocols to sync our repositories. But the important distinction here is that this is a two step process. First you fetch content from remote. This is simply ensuring you have all the commit objects you need in your local git database. Any branches you have are simply text files with the commit content hash they point to as the content in .git/refs/heads. Remote branches are the same but live in your local .git/refs/remotes/<remotename>. Those branches might be named something like origin/main to make it clear that that is a local branch from the origin remote. And then you rebase/merge between your local and "remote" (i.e. also local) branch as needed. Pull is just short hand for doing both steps in one go. All merges are local. Same with rebases.
Most of the conventions people project on git are kind of cultural and vary between people and companies. It's helpful to read up on the git internals in the Git book. Github is sort of an opinionated take on this that back in the day made people coming from centralized version systems like subversion feel at home by providing a central repository and allowing them to push their changes there or "share" branches there. Not necessarily a great idea for bigger projects and limiting write access is common on Github.
- pdonis 3y ago> The branch name isn't even part of the patch. More generally, the branch name is not stored with commits; it has to be computed by walking back from the branch tips, and commits can have multiple possible branch names based on this. In other words, git does not preserve information about which branch was actually active when you made a particular commit. (Mercurial, by contrast, stores the branch that was active when a commit was made in the commit, so that information is preserved.) The article discusses some implications of this, although it doesn't phrase it quite the way I did above.
- PaulDavisThe1st 3y ago> A git patch is just a textualized form of the list of commits you created locally. You can apply them to any branch you like. Not even branch. You can combine two unrelated repositories, and in theory you could cherry-pick commits from one of the original repositories to the other. Of course, in practice this rarely works because the files mentioned in the commit don't exist in the other repository. But there's nothing in git's mechanisms that stops this: it's just a bunch of commits, which are actually just a bunch of file contents. The whole "diff" or "patch" concept in git is just way of doing data presentation - rather than showing you the actual commit, which is generally not helpful, it shows you the difference between the contents of the commit, and the same files in the state referenced by the previous commit.
- jillesvangurp 3y agoGit commits always have a parent. Applying git patches to a repository without the parent is not going to work. The repository must have the parent commit. You might force it to work without that but it's going to create conflicts, complicate merging, etc. The reason is that a git patch is not merely a diff but an export of the actual commit objects and referred content (trees, blob diffs, hashes, etc.). Applying the patch recreates the exact commit objects on the other side. The end state is exactly the same as if you would have merged the commits from some branch. There is no difference. Git diff, shows you a normal diff. It's not the same thing. You can indeed apply such diffs to your local work copy. But that's not the same thing as a git patch. The commands you need are git format-patch (exports the patch) and git apply (applies it).