On 12/4/17 3:14 PM, Ali Çehreli wrote:
Dear git experts, given 3 repos, now what are the steps? Is the
following correct? What are the exact commands?
Disclaimer: I'm not a git expert.
- Only once, create the original repo as an upstream of your local repo.
The wording is off (s/repo/remote), but yes. This one I always have to
look up, because I don't remember the order of the URL vs. the name, and
git doesn't care if you swap them. But the command is this:
git remote add upstream <url>
Where url is the https version of dlang's repository (IMPORTANT: for
dlang members, do NOT use the ssh version, as then you can accidentally
push to it without any confirmation).
- For each change:
1) Fetch from upstream
git fetch upstream
will fetch EVERYTHING, all branches. But just for reference so you can
use it without affecting your local repo.
2) Rebase origin/master (on upstream, right?)
No, don't do this every time! If you never commit to your local master
(which you shouldn't), you do it this way:
# This checks out your local master branch
git checkout master
# This moves your local master branch along to match that of master.
# The --ff-only is to ensure it only works if the merge is a fast-forward.
# A fast forward merge happens when your master is on the same commit
# history as the upstream master.
git merge --ff-only upstream/master
Optionally you can push your local master to origin, but it's not
strictly necessary:
git push origin master
3) Make changes
Step 2.1: checkout a local branch. You can even do this after you have
changed some files but *before* you have committed them (IMO one of the
best features of git as compared to, say, subversion).
# creates a new branch called mylocalfix based on local master, and
checks it out.
git checkout -b mylocalfix
4) Commit (potentially after 'add')
Protip: git commit -a automatically adds any modified files that are
currently in the repo, but have been changed.
5) Repeat steps 3 and 4 as needed
Correct!
6) 'git push -force' so that your GitHub repo is up-to-date right?
(There, I mentioned "force". :) )
I'd say:
git push origin mylocalfix
This pushes *only* your mylocalfix branch to *your* fork of the repo.
No need to force as long as you do not want to squash. Squashing is when
you merge multiple commits into one commit so that the history looks
cleaner. I'd recommend never using force (btw, it's --force with 2
dashes) unless it complains. And then, make sure you aren't doing
something foolish before using the --force command! Because you are
committing only to your fork, and to your branch, even if you mess up
here, it's pretty easy to recover.
A couple of examples:
1. You commit, but missed a space between "if" and "(". Instead of
generating a commit and log for the typo, you just squash the new commit
into the first one.
2. You commit a work in progress, but then change the design. The first
commit is useless in the history, as it probably doesn't even apply
anymore, so you squash them together, as if you only ever committed the
correct version.
To squash the last few commits, I recommend using rebase -i:
# Replace 3 with the number of the last few commits you want to work with.
# IMPORTANT: this must contain the commit you want to squash into!
git rebase -i HEAD~3
This will pop up an editor. Follow the instructions listed there! If you
want to squash 2 commits together, use "fixup", or even just "f". Note:
do NOT "fixup" your first commit, as this will try to squash into
someone else's commit that happened before you changed anything!
Once you write the file and exit, git will rebase using your directions.
At this point you need to use --force to push (as long as you have
already pushed before), as your commit history now differs from github's.
7) Go to GitHub and press the big button to create a pull request
Correct! After you do this, you can continue to run steps 3, 4, 6 to
update your PR.
One further step that I like to do to keep my repo clean:
8) When your PR is pulled:
git fetch upstream
git checkout master
git merge --ff-only upstream/master
git branch -d mylocalfix
This pulls the new changes that were successfully merged into dlang's
master into your master. Then it deletes the mylocalfix branch (no
longer needed). The lower case -d means to only delete if the changes
have been merged (git will complain if they aren't in the history). This
is a nice way to clean your local branches up, and verify there isn't
anything amiss.
Note also, if you want to work on several fixes at once, you can
checkout more than one local branch, and switch between them. Just
remember to commit before you checkout the different branches (git will
complain if you have uncommitted files, but not files that haven't ever
been added).
Hope this all helps!
-Steve