Is there a way to write an alias that merges a branch back to its parent? I know I can do:
git checkout - && git merge -
But it only works in simple cases when my previous branch is the parent branch.
As far as I know git does not track this kind of information because there is no branches in there. But I hope it's already implemented as a plugin or a hookset.
Thanks in advance.
Such an alias would involve first finding the "parent" branch.
It isn't trivial, and the question "Find the parent branch of a branch" has some good solutions.
Git’s history is based on a DAG of commits. Branches (and “refs” in general) are just transient labels that point to specific commits in the continually growing commit DAG.
As such, the relationship between branches can vary over time, but the relationship between commits does not.
Once you have the name of the parent branch, then you can use it in your alias.
As VonC said first I need to do is to find parent of the current branch. The following script mostly does what I need:
git branch | grep -v '*'|xargs -I{} sh -c ' printf "{}:"; git log --oneline `git merge-base "$(git rev-parse --abbrev-ref HEAD)" "{}"` | wc -l' | sort -t: -k +2n | tail -n 1 | sed 's/:.*//'
What it does:
For each branch finds merge-base with the current branch
Finds branch:log-length pair maximizing log-length
Extracts branch name
After that one just need to checkout to it and merge previous head into it:
git checkout $parent_branch && git merge -
PS: I didn't test it on large repositories and it can behave suprisingly if exists a branch of the current branch. It needs to be fixed.
Related
In git it is possible to show an ASCII graph of the log with git log --graph which outputs a commandline graph something like:
* 040cc7c (HEAD, master) Mannual is NOT built by default
* a29ceb7 Removed offensive binary file that was compiled on my machine
| * 901c7dd (cvc3) cvc3 now configured before building
| * d9e8b5e More sane Yices SMT solver caller
| | * 5b98a10 (nullvars) All uninitialized variables get zero inits
| |/
| * 1cad874 CFLAGS for cvc3 to work succesfully
|/
* d642f88 Option -aliasstat, by default stats are suppressed
Is this also possible with ClearCase / ClearTool when using the lsstream or lsvtree commands, without the need to open a GUI?
Since I couldn't find anything that suited me, I created my own python script with this ability. It is still a little rough, but works for me.
For anyone interested, it is available here as a github gist
With command line, you have cleartool lsvtree.
If you want the history to focus on the branch you currently are (instead of starting by default at /main), you need to use the -bra/nch branch-pname option.
Starts the version tree listing at the specified branch.
You can also use an extended name as the pname argument (for example, foo.c##\main\bug405) to start the listing at a particular branch.
But if you need additional information like the author, then you would need to fallback to cleartool lshistory: see "How to ask cleartool lsvtree to show the author's name"
I created a branch and committed a changeset as a child of a child of my main branch. I actually meant to shelve the changes and create a new branch off of my main branch. How can I revert and/or make the branch a direct child of my main branch?
I have a hunch that I will need to revert or do a subtractive merge.
For PlasticSCM, the idea would similar to what is described below for Git:
having a branch referring to your current commit
reset the branch to the last correct commit
use the switchbranchbase command mention for PlasticSCM4 or the simple merge mention in this thread.
In PlasticSCM 3.0 to perform a rebase the steps were: Change branch base, update, merge.
In PlasticSCM 4.0 is easier, just perform the merge from the branch you want to rebase.
Original answer in git:
If you have:
x--x--x--x main
\
y--y--y child
\
z--z mybranch
You can do a:
git rebase --onto main child mybranch
That would give you:
z'--z' mybranch
/
x--x--x--x main
\
y--y--y child
If you didn't want to rebase all of my branch, then a simple:
git checkout mybranch
git branch -b mynewbranch
git reset --hard z # reset mybranch HEAD to the last commit before your new commit
git rebase --onto main mybranch mynewbranch
For a single commit, you could also use git cherry-pick, but I always prefer git rebase.
I have somehow created a branch of a file in clearcase UCM that is not part of an activity. I have no idea how to reproduce this, but my stream is showing many files with this symptom. How can I find these files, remove them, and prevent it from happening again in the future?
Here is an example of one such file, names redacted to protect the innocent:
xxxxxxxxxxx.cpp##/main/xxx-integration/xxxxxx-xxxxxxxx/0 Rule: .../xxx-xxxxxxx/LATEST
A ct lsact -long | grep <filename> returns no results.
Update:
I used a find command to track down all the files that are on the branch given (and redacted) above, though I still do not understand the issue.
Per VonC's answer, where is what I ended up doing:
cleartool find . -type f -version "version(.../xxx/LATEST)&&version(.../xxx/0)" -print | tee ~/tmp/files2
I then read through the list of files generated to make sure they made sense, then I verified they were not attached to an activity and removed the versions:
cat ~/tmp/files2 | while read
do
if [ -z "$(ct describe -fmt "%[activity]p" $REPLY)" ]
then
ct rmbranch -f ${REPLY%/0}
fi
done
That can happen ig those file were checkout in a base ClearCase view, ie a non-UCM view, withg a simple config spec:
element * .../xxx-integration/LATEST -mkbranch xxxxxx-xxxxxxxx
You can use a find command similar to "How can I find all elements on a branch with version LATEST that has no label applied?".
The difference is: for each version found, you need to describe it in order to check if there is an activity attached to it or not (with a fmt_ccase):
cleartool describe -fmt "%[activity]p" "$CLEARCASE_XPN"
I'm looking to find the number of times that each file has changed on a particular branch in our cvs repository. I'm particularly looking for all the files which have changed the most. A "top 40" list would be good enough.
This was added as an edit by the original asker, I have converted it to a community wiki answer because it should be an answer, not an edit.
In this case, the branch has been in use for about 6 months. If I set to the latest in that branch ("cvs -z9 co -r r80m-1 ..."), it looks like the last number of the revision is the number of changes in the current branch -- if the file has been changed in the past 180 days, then it's on this branch. I'm using linux, so I eventually did it this way:
for file in `find . \! \( -name CVS -prune \) -type f -mtime -180`
do
cvs status "$file" | grep Working.revision | gawk -v FNAME=$file '{ print FNAME gensub(/(\.)([0-9]*)$/, "\\1\\2 churn:\\2 ", 1) }' >> cvs_churn.txt
done
sort -k3 -t: -n cvs_churn.txt | uniq
So, for each line in "cvs status" output like:
Working revision: 1.2.34
The gawk command changes it to:
./path/file.c Working revision: 1.2.34 churn:34
and I can then sort on ":34".
This works, but it's pretty crude. I'm hoping others may be able to answer with better approaches.
I've seen in some other questions eg: Free CVS reporting tools people have mentioned statCVS. It sounds interesting (more than I need, but some of the other info might also be useful). However, it says it only works on the "default" branch. The documentation was a little unclear -- can I set to the branch of interest, and use it for this?
I have a CakePHP project under Mercurial version control. Right now all the files in the app/tmp directory are being versioned, which are always changing.
I do not want to version control these files.
I know I can stop by running hg forget app/tmp/*
But this will also forget the file structure. Which I want to keep.
Now I know that Mercurial doesn't version directories, just files, but the CakePHP folks were also smart enough to put an empty file called empty in every empty directory (I am guessing for this reason).
So what I want to do is tell Mercurial to forget every file under app/tmp except files whos name is exactly empty.
What would the command be for this?
Well, if nothing else works, you can always just ask Mercurial to forget everything, and then revert empty before committing:
Here's how I reproduced it, first create initial repo:
hg init
md app
md app\tmp
echo a>app\empty
echo a>app\tmp\empty
hg commit -m "initial" -A
Then add some files we later want to get rid of:
echo a >app\tmp\test1.txt
echo a >app\tmp\test2.txt
hg commit -m "adding" -A
Then forget the files we don't want:
hg forget app\tmp\*
hg status <-- will show all 3 files
hg revert app\tmp\empty
hg status <-- now empty is gone
echo glob:app/tmp>.hgignore
hg commit -m "ignored" -A
Note that all .hgignore does is to prevent Mercurial from discovering new files during addremove or commit -A, if you have explicitly tracked files that match your ignore filter, Mercurial will still track changes to those files.
In other words, even though I asked Mercurial to ignore app/tmp above, the file empty inside will not be ignored, or removed, since I have explicitly asked Mercurial to track it.
At least theoretically (I don't have time to try it right now), pattern matching should work with the hg forget command. So, you could do something like hg forget -X empty while in the directory (-X means "exclude").
You may want to consider using .hgignore, of course.
Since you only need to do it once I'd just do this:
find app/tmp -type f | grep -v empty | xargs hg forget
hg commit
from then on just put this in your `.hgignore'
^app/tmp
Mercurial has built-in support for globbing and regexes, as explained in the relevant chapter in the mercurial book. The python regex implementation is used.
This should work for you:
hg forget "re:app/tmp/.*(?<!/empty)$"