Branching.hpp File Reference

Todos and plans regarding branching. More...

Go to the source code of this file.

Detailed Description

Todos and plans regarding branching.

Purely local branches
  • For a local branch (not to be exported) the standard model is as follows:
    1. Create branch B by "git branch B" (while current branch being master).
    2. Once master has been updated, update B by "git merge master" (being on branch B).
    3. Finally, for abandoning B, use "git merge B" (being on branch master).
    4. Removal of B then by "git branch -d B" (deleting B).
  • If the branch really is never exported, then the following model provides an alternative, where the history of the branch is linearised:
    1. Everything as above.
    2. Except that when master has been updated, B is updated now by "git rebase master" (being on branch B).
    3. In this way the history of B is rewritten, but this might not be relevant.
    4. When finally abonding B, it must still be merged as above.
  • However, outside of this situation I don't see a use of "rebase":
    1. The change of history doesn't seem to be a fundamental problem, since in case of conflict with some external repository, git automatically creates an appropriate merge.
    2. But it seems to me that then the standard merge is to be preferred.
Problems with branch rijndael:
  • We don't have branch rijndael anymore, but the problems are symptomatic.
  • Git-gui used to allow to switch branches, but then it stopped doing so??
  • Merge cascades still occur --- the key is to understand the merge-model of git, and its implications on how to reach a fixed point.
  • Likely we have to ask these questions on the git-mailing-list.
  • Why are there these merge-cascades? Apparently on my laptop I merge master into rijndael, then on the workstation again, and then again on the server (without wanting to do so)??? It seems that setting up the pull's so that they automatically merge branches master and rijndael doesn't work nicely: Every different repository performs the merge again, and does not recognise that this has already happened. (Why is this the case? A bug?) So the cure is that every branch just pulls "itself", and no automatic merges (different from what is proposed below). It is then the responsibility of the submitter to make sure that branch rijndael is always a superset of of branch master. DONE (in this way it works reasonably)
Tutorial on branching : DONE (basic principle are understood; needs to be transferred to the documentation-document)
  • Creating a (completely new) branch is a (purely) local matter; the name is better unique (different form files or other branches). Let's call it "br" for demonstration here, then the basic command is
    git branch br
    which can be checked by git branch (whether the branch has been created), while switching to the branch happens via
    git checkout br
    This can be combined into one step via
    git checkout -b br
    The new branch by default will contain the full history of the branch on which the branch-creation command was issued (one can go back in history by adding a start-point like a sha1-hash-value after the name of the new branch).
  • A cloned repository automatically "tracks" branches from the master clone, that is, when issuing "git pull" then the changes to the remotely tracked branches are stored (but don't result in branches; one can see them via gitk --all, but apparently one cannot do anything else with this stored information?).
  • When setting up the new branch (see above), then one can use instead
    git branch --track br 
    which has the only meaning that when "git pull" is issued when on branch br, then the changes of the branch m on which the branch-creating-command was issued (the tracked branch) are merged into br. So it appears to be just a sort of shortcut to issuing
    git merge m
    when on branch br.
  • With the new local branch br (yet nobody else knows about it) one can work, do all sorts of things, and its typical destination is to be merged into another branch m via
    git merge br
    when on branch m, and then possibly deleting the branch via git branch -d br when on another branch. (It seems that somewhat strange things can happen when working further with br (for example files created on br suddenly appear on m as untracked files)? But it should be normal to do so?)
  • Now pushing a new branch to the shared central repository doesn't just happen via "git push" now, since this pushes all "references" which exist locally *and* on the remote repository, and yet there is no reference on the master clone (the repository to which "git push" is adressed when not further specified, which we assume is normally the shared central repository). To make the branch available use
    git push origin br:br
    where "origin" is the git-abbreviation of the url of the master clone (instead of "origin" any other url of any other git-repository can be used), and "br:br" is a short version of the full "refspec", the specification of the reference at the source (on the left-hand side; this is the current repository) and at the destination (on the right-hand side; note that one can push to any other branch, either existing or new (then created), but then there would be no automatic link between the histories of the local branch br and the remote branch br_remote). Alternatively one can use
    git push --all
    pushing all existing references.
  • Now when on the central shared repository the new branch has been created, then, via the automatic tracking, a "git pull" on another clone (of the central shared repository) will pull it in, but not creating a new branch, which needs a special checkout-command; the whole sequence on the clone then is
    git pull
    git checkout --track -b br origin/br
    where, as discussed above, the "--track" option just has the result, then when issuing "git pull" (no further arguments) on branch br, then a merge from the central repository of branch br is performed).
  • It appears, that actually git doesn't know about the assumed relation between for example branch br on the shared central repository and on the clone: Every branch is always local, and that they have the same name as some branch somewhere else is considered to be purely coincidental --- only the tracked references make some branches automatically merge into other branches (namely "git pull" on branch m will fetch and merge the referenced branch into m).
  • In the above example, the creator of branch br has a different relation to it then the other which just copies it:
    1. The creator tracks branch m (possibly the master-branch) and thus is responsible for keeping br up-to-date with m (without the "--track"-option there would be no default relation to any other branch).
    2. The other (the copier) only tracks the changes coming from the central repository.
    Perhaps this asymmetry is not appropriate (the creator was just the first one, like the first one creating a file, but then other join in), and then in file .git/config more complicated relations have to be established. For example, on the copying clone the entry for tracking branch br from the central repository is
    [branch "br"]
            remote = origin
            merge = refs/heads/br
    which sets variable branch.br.merge to "refs/heads/br", the default for "git pull" (without arguments). Now this variable can have a multiple values (realised by several assignments(!)), and so in this case several remote branches can be pulled at once. The above sets also variable branch.br.remote to "origin", where here apparently only one value (not a list) is allowed, namely the repository from which "git pull" will pull by default; for tracking something from the local repository the special value "." for remote is used, so for example for the creator of branch br:
    [branch "br"]
            remote = .
            merge = refs/heads/master
    It appears not to be possible to combine local and remote merges.
  • As an aside, such variable settings can either be handling by editing file .git/config, or by using for example
    git config branch.br.merge "refs/heads/br"
    git config --add branch.br.merge "refs/heads/m"
    which would for the copying clone result in not just following the central version of br, but also the "master"-branch m. For the creator of branch m, who currently has to use
    git pull origin br
    to get the changes from the repository (recall that he tracks the local branch m), it would make sense to use
    git config branch.br.remote "origin"
    git config branch.br.merge "refs/heads/br"
    git config --add branch.br.merge "refs/heads/m"
    to get the same settings.
  • We remark the asymmetry between pull and push: With "git pull" one only gets the specific branches which are referenced by the current branch (except of that somewhat strange situation, where a new branch appears on the master clone), while via "git push" one pushes all currently referenced connections (not just on the current branch).
  • Finally, merging br with its "master" m (abandoning br) happens via issuing by someone on the (respective) master-branch m
    git merge br
    followed by
    git branch -d br
    on the central repository(!), followed by
    git branch -d br
    on all local copies.
On branching (in our situation) DONE (fixed a reasonable procedure; needs to be transferred to the general documentation))
  • The appropriate routine for creating a new branch br by developer D and making it available on the shared repository seems to be as follows:
    1. D in the master branch issues
      git branch br
      followed by making it known
      git push origin br:br
      (or, easier, by git push --all), followed by setting tracking behaviour (tracking master and br remotely)
      git config branch.br.remote "origin"
      git config branch.br.merge "refs/heads/br"
      git config --add branch.br.merge "refs/heads/master"
    2. Anybody else picks it up by
      git pull
      git checkout -b br origin/br
      git config branch.br.remote "origin"
      git config branch.br.merge "refs/heads/br"
      git config --add branch.br.merge "refs/heads/master"
    3. Pushing now via git push means pushing all (committed) changes to the central repository (all branches), while git pull on some branch will pull in all changes related to the current branch only.
    4. In order to have pulls which combine different pull-actions, in .git/remotes for example the file "Laptop" has been created with the content
      URL: ~LaptopArchiv/OKsystem/OKlib/
      Push: master:master
      Push: rijndael:rijndael
      Pull: master:master
      Pull: rijndael:rijndael
      which means, that by using git pull Laptop both branches are updated from the Laptop-archive (independently), and that by "git push" one could push both branches (as said elsewhere, "pull" seems to be better than "push" in case of non-bare repositories) --- this works independently of the branch from where the pull/push is issued.
    5. Since br is assumed to be an extension of m, normal works happens in branch br, but when committing files, one has to take care only to commit the special files, while for the other files one changes to branch m (via git checkout m; after all committs in branch br have been handled --- otherwise git won't switch).
    6. Finally abandoning the branch, re-merging it into master via
      git merge br
      while on branch master, followed by
      git branch -d br
      on the central repository and each local clone.
  • It appears that "secret" development cannot be achieved via branching, but a new dedicated repository has to be created.

Definition in file Branching.hpp.