This shows you the differences between two versions of the page.

Link to this comparison view

misc:git-doc [2018/08/14 11:25] (current)
Line 1: Line 1:
 +====== git's cookbook for OpenSDE ======
 +I'll start by the most basic request, **PLEASE** read ''​git'​s''​ [[http://​www.kernel.org/​pub/​software/​scm/​git/​docs/​|documentation]]! ''​git''​ is very well documented.
 +If you still here I guess you decided that the official [[http://​www.kernel.org/​pub/​software/​scm/​git/​docs/​|documentation]] was to tough for you. Then you can try a different kind of documentation,​ one focused on understanding how ''​git''​ works instead of how ''​git''​ is supposed to be used.
 +    * [[http://​www.newartisans.com/​blog_files/​git.from.bottom.up.php|git from bottom up]]
 +    * [[http://​eagain.net/​articles/​git-for-computer-scientists/​|git for computer scientists]]
 +but this guide is an OpenSDE-centric //​cookbook//,​ so we will explain how to use ''​git''​ on our context.
 +===== OpenSDE structure =====
 +//OpenSDE// itself is composed by two [[http://​git.or.cz/​|git]] repositories,​ one for the [[http://​git.opensde.net/​opensde/​opensde-nopast/​|framework]] and one for the [[http://​git.opensde.net/​opensde/​package-nopast/​|packages database]].
 +These repositories currently don't include the past of the project which partially comes from [[http://​www.rocklinux.net/​svn/​rock-linux/​|RockLinux]]'​s,​ [[http://​svn.exactcode.de/​t2/​|T2]] and our own old [[http://​subversion.tigris.org/​|Subversion]] repository. The task of importing these commits into a new and more complete ''​git''​ repository has been postponed.
 +In OpenSDE the //targets// are considered //​sub-projects//​ so they have their own repositories. And we also support external repositories in ''​package/​repo''​. ''​sde up''​ currently handles these external repositories when they are ''​svn''​ or ''​git''​.
 +==== The sde wrapper ====
 +On OpenSDE we provide a //silver bullet// tool which tries to hide some //version control system// specifics, to help in the //​building//​ and //​maintaining//​ processes, and to encourage some "​recommended"​ practices while reducing the effort for the user.
 +But ''​sde''​ can't (and should not) wrap the entire ''​vcs''​ functionality,​ just the most common actions.
 +''​sde''​ is designed to run from ''​$PATH'',​ from any directory, understanding the context and using that knowledge to make user's life a bit easier.
 +The ''​sde''​ wrapper takes the commands from the //working directory// you are using, so it's version independent.
 +===== Getting the tree =====
 +When you already have an //OpenSDE working tree//, and ''​sde''​ in your ''​$PATH'',​ creating a new tree is very simple.
 +  $ cd somewhere
 +  $ sde new tree mynewtree
 +And this will use ''​git''​ to get the //opensde repo// from the same location you were using before in ''​somewhere/​mynewtree''​ and also the corresponding ''​somewhere/​mynewtree/​package''​.
 +If you don't have //OpenSDE// yet the steps are the following (need ''​git''​ installed):
 +  $ cd somewhere
 +  $ git clone git://​git.opensde.net/​opensde/​opensde-nopast mynewtree
 +  $ cd mynewtree
 +  $ git clone git://​git.opensde.net/​opensde/​package-nopast package
 +==== Getting sde ====
 +It is a **very** good idea to install ''​sde''​ in your ''​$PATH''​. to do that go to the root of your //OpenSDE tree// and:
 +  $ ./bin/sde install
 +This will symlink ''​bin/​sde''​ of this //working tree// into your ''​$HOME/​bin'',​ which is supposed to be in the head of your ''​$PATH''​. Most distributions do this automatically,​ if the directory exists when you //log-in//. So logging out and back in may solve the issue. If not, you may want to add it on your own ''​$HOME/​.profile''​ as:
 +  export PATH="​$HOME/​bin:​$PATH"​
 +If you //cloned// ''​opensde-nopast''​ using ''​git''​ and you already put ''​sde''​ in your ''​$PATH'',​ ''​sde up''​ will get ''​package-nopast''​ for you if it's still missing.
 +==== Staying up to date ====
 +In //OpenSDE// staying up to date is very easy, even when you have local commits which you don't want to send //​upstream//​ (push) yet. But you have to remember ''​git'',​ unlike ''​svn''​ needs your //working tree// clean of //​uncommited//​ changes.
 +  $ sde up
 +And your tree (including //​framework//,​ //​packages//​ and //​targets//​) will be up to day.
 +To do it by hand you have to use ''​git''​ on each //repo//. (don't forget the //​--rebase//​ part).
 +  $ git pull --rebase
 +but when you are working on a local branch and you don't want upstream changes injected on it //yet// use:
 +  $ git fetch
 +and ''​origin/​master''​ will reflect the current //​upstream//​ state, but your local //branch// wont be touched.
 +===== Branches =====
 +We inherited //​subversion//​ from our predecessor. ''​svn''​ is great but not for us because:
 +  - you need to be //online// to work with it.
 +  - to merge from branch is //painful//
 +We encourage people to work on public branches so we can all comment, contribute, and test before the final code hits the //trunk// (//tip// or //​master//​).
 +But the problems shown above make people work on (private) //working trees// plenty of //​uncommited//​ changes, and out of sync with //​upstream//​.
 +==== Creating a branch ====
 +The first question is, a //branch of what?// ... let see what we have
 +  $ git branch -a
 +  * master
 +    origin/HEAD
 +    origin/​master
 +    origin/​foobar
 +Assuming you want a //local// branch (on which you could work) corresponding to //​upstream//'​s ''​origin/​foobar''​ we create a //​tracking//​ branch using:
 +  $ git checkout -b foobar origin/​foobar
 +This will bind the local //branch// "​foobar"​ with the remote branch of the same name, in the //remote// named "​origin"​.
 +The other common case is to branch your current local "​master"​ so you can:
 +  -commit all the //​uncommited//​ changes you have in your messy //working directory// to be able to get in sync with upstream again.
 +  -push some commits upstream but not all, without loosing them.
 +  -move your work to a different //topic// branch.
 +  -start a new //topic// branch starting at this point.
 +The first step for all of these cases is:
 +  $ git checkout -b mynewbranch
 +and now you are at "​mynewbranch"​ instead of "​master",​ which can be confirmed using ''​git branch''​.
 +If you are on case 1, the next step is to ''​git add'',​ ''​git rm''​ and ''​git mv''​ what have have in git status, and make a monster git commit, or if you are terribly lazy ''​git commit -a''​
 +Then you can return to "​master"​ using ''​git checkout master''​. Once back in "​master",​ if you were on case 1, ''​git pull --rebase''​ should work.
 +If you were in cases 2 or 3, ''​git rebase -i origin/​master^''​ will let you remove those commits which you want in "​mynewbranch"​ but not in "​master"​ yet so you can push just a selected bunch.
 +==== Using branches ====
 +We don't like ''​git merge''​ (that'​s why we don't use use ''​git pull''​),​ we like to keep the commits //atomic//, not as a big monster commit as ''​git merge''​ produces.
 +It's perfect (and recommended) to create a branch to update (and test) all the packages related to the last //foo// release. But the updates of each package shall remain separated.
 +When one keeps branches, it's common to want to include on a branch a commit done in another branch. This is done using ''​git cherry-pick <​hash>'',​ but you don't need the whole //hash// of the //commit//, instead the first 6-8 characters are usually enough.
 +  $ git log otherbranch | less               # to identify the commit
 +  $ git cherry-pick 1a2bcd
 +Another common case is when you want to //​cherry-pick//​ a range of commit, but ''​git cherry-pick''​ doesn'​t support ranges, so we need to loop. Assuming we want to merge from ''​aabbcc''​ (older) to ''​ddeeff''​ (newer), including both the shell loop would look like:
 +  $ for hash in $(git rev-list aabbcc^..ddeeff | tac); do
 +  > git cherry-pick $hash;
 +  > done
 +The last case is when you want to //​cherry-pick//​ many commit, in this case the easier way is to branch that other branch, and then rebase it interactively to yours, so you remove those commits you don't want.
 +  $ git checkout the_other_branch
 +  $ git checkout -b a_new_one ​               # make a copy of that other branch
 +  $ git rebase -i the_one_im_working_on ​     # to remove those commits you don't want
 +  $ git branch -d the_one_im_working_on ​     # careful! this is a delete!
 +  $ git checkout the_other_branch ​           # you can't rename the current, so go out
 +  $ git branch -m a_new_one the_one_im_working_on ​  # the rename
 +Another way of working with ''​git''​ (more like a complementary way to //​branches//​) is presented at [[git-stash]].
 +==== Pushing a branch ====
 +To //push// a branch means to send your local commits upstream
 +==== Deleting a branch ====
  • misc/git-doc.txt
  • Last modified: 2018/08/14 11:25
  • (external edit)